diff options
Diffstat (limited to 'src')
60 files changed, 776 insertions, 101 deletions
diff --git a/src/.clang-format b/src/.clang-format index a69c57f3e0..791b3b8f9f 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -34,14 +34,6 @@ IndentWidth: 4 KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: 2 NamespaceIndentation: None -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: false -PenaltyBreakBeforeFirstCallParameter: 1 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements @@ -51,6 +43,5 @@ SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false -Standard: Cpp11 -TabWidth: 8 +Standard: c++17 UseTab: Never diff --git a/src/Makefile.am b/src/Makefile.am index 85450149cf..6cfd5a9050 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -709,7 +709,18 @@ bitcoin_wallet_SOURCES += init/bitcoin-wallet.cpp bitcoin_wallet_CPPFLAGS = $(bitcoin_bin_cppflags) bitcoin_wallet_CXXFLAGS = $(bitcoin_bin_cxxflags) bitcoin_wallet_LDFLAGS = $(bitcoin_bin_ldflags) -bitcoin_wallet_LDADD = $(LIBBITCOIN_WALLET_TOOL) $(bitcoin_bin_ldadd) +bitcoin_wallet_LDADD = \ + $(LIBBITCOIN_WALLET_TOOL) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBUNIVALUE) \ + $(LIBBITCOIN_CONSENSUS) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBSECP256K1) \ + $(BOOST_LIBS) \ + $(BDB_LIBS) \ + $(SQLITE_LIBS) if TARGET_WINDOWS bitcoin_wallet_SOURCES += bitcoin-wallet-res.rc diff --git a/src/Makefile.test.include b/src/Makefile.test.include index da4b85665f..402cf188c4 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -16,6 +16,7 @@ FUZZ_BINARY=test/fuzz/fuzz$(EXEEXT) JSON_TEST_FILES = \ test/data/script_tests.json \ + test/data/bip341_wallet_vectors.json \ test/data/base58_encode_decode.json \ test/data/blockfilters.json \ test/data/key_io_valid.json \ diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 338d32ef6b..279521a761 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -49,6 +49,7 @@ static constexpr int DEFAULT_WAIT_CLIENT_TIMEOUT = 0; static const bool DEFAULT_NAMED=false; static const int CONTINUE_EXECUTION=-1; static constexpr int8_t UNKNOWN_NETWORK{-1}; +static constexpr std::array NETWORKS{"ipv4", "ipv6", "onion", "i2p", "cjdns"}; /** Default number of blocks to generate for RPC generatetoaddress. */ static const std::string DEFAULT_NBLOCKS = "1"; @@ -242,11 +243,10 @@ public: class AddrinfoRequestHandler : public BaseRequestHandler { private: - static constexpr std::array m_networks{"ipv4", "ipv6", "onion", "i2p"}; int8_t NetworkStringToId(const std::string& str) const { - for (size_t i = 0; i < m_networks.size(); ++i) { - if (str == m_networks.at(i)) return i; + for (size_t i = 0; i < NETWORKS.size(); ++i) { + if (str == NETWORKS[i]) return i; } return UNKNOWN_NETWORK; } @@ -269,7 +269,7 @@ public: throw std::runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up"); } // Count the number of peers known to our node, by network. - std::array<uint64_t, m_networks.size()> counts{{}}; + std::array<uint64_t, NETWORKS.size()> counts{{}}; for (const UniValue& node : nodes) { std::string network_name{node["network"].get_str()}; const int8_t network_id{NetworkStringToId(network_name)}; @@ -279,8 +279,8 @@ public: // Prepare result to return to user. UniValue result{UniValue::VOBJ}, addresses{UniValue::VOBJ}; uint64_t total{0}; // Total address count - for (size_t i = 0; i < m_networks.size(); ++i) { - addresses.pushKV(m_networks.at(i), counts.at(i)); + for (size_t i = 0; i < NETWORKS.size(); ++i) { + addresses.pushKV(NETWORKS[i], counts.at(i)); total += counts.at(i); } addresses.pushKV("total", total); @@ -363,14 +363,13 @@ class NetinfoRequestHandler : public BaseRequestHandler { private: static constexpr uint8_t MAX_DETAIL_LEVEL{4}; - static constexpr std::array m_networks{"ipv4", "ipv6", "onion", "i2p"}; - std::array<std::array<uint16_t, m_networks.size() + 1>, 3> m_counts{{{}}}; //!< Peer counts by (in/out/total, networks/total) + std::array<std::array<uint16_t, NETWORKS.size() + 1>, 3> m_counts{{{}}}; //!< Peer counts by (in/out/total, networks/total) uint8_t m_block_relay_peers_count{0}; uint8_t m_manual_peers_count{0}; int8_t NetworkStringToId(const std::string& str) const { - for (size_t i = 0; i < m_networks.size(); ++i) { - if (str == m_networks.at(i)) return i; + for (size_t i = 0; i < NETWORKS.size(); ++i) { + if (str == NETWORKS[i]) return i; } return UNKNOWN_NETWORK; } @@ -471,10 +470,10 @@ public: const bool is_outbound{!peer["inbound"].get_bool()}; const bool is_block_relay{!peer["relaytxes"].get_bool()}; const std::string conn_type{peer["connection_type"].get_str()}; - ++m_counts.at(is_outbound).at(network_id); // in/out by network - ++m_counts.at(is_outbound).at(m_networks.size()); // in/out overall - ++m_counts.at(2).at(network_id); // total by network - ++m_counts.at(2).at(m_networks.size()); // total overall + ++m_counts.at(is_outbound).at(network_id); // in/out by network + ++m_counts.at(is_outbound).at(NETWORKS.size()); // in/out overall + ++m_counts.at(2).at(network_id); // total by network + ++m_counts.at(2).at(NETWORKS.size()); // total overall if (conn_type == "block-relay-only") ++m_block_relay_peers_count; if (conn_type == "manual") ++m_manual_peers_count; if (DetailsRequested()) { @@ -571,7 +570,7 @@ public: for (int8_t n : reachable_networks) { result += strprintf("%8i", m_counts.at(i).at(n)); // network peers count } - result += strprintf(" %5i", m_counts.at(i).at(m_networks.size())); // total peers count + result += strprintf(" %5i", m_counts.at(i).at(NETWORKS.size())); // total peers count if (i == 1) { // the outbound row has two extra columns for block relay and manual peer counts result += strprintf(" %5i", m_block_relay_peers_count); if (m_manual_peers_count) result += strprintf(" %5i", m_manual_peers_count); diff --git a/src/init.cpp b/src/init.cpp index b0335183d6..f659de3a02 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1102,11 +1102,6 @@ bool AppInitLockDataDirectory() bool AppInitInterfaces(NodeContext& node) { node.chain = node.init->makeChain(); - // Create client interfaces for wallets that are supposed to be loaded - // according to -wallet and -disablewallet options. This only constructs - // the interfaces, it doesn't load wallet data. Wallets actually get loaded - // when load() and start() interface methods are called below. - g_wallet_init_interface.Construct(node); return true; } @@ -1170,6 +1165,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler); + // Create client interfaces for wallets that are supposed to be loaded + // according to -wallet and -disablewallet options. This only constructs + // the interfaces, it doesn't load wallet data. Wallets actually get loaded + // when load() and start() interface methods are called below. + g_wallet_init_interface.Construct(node); + uiInterface.InitWallet(); + /* Register RPC commands regardless of -server setting so they will be * available in the GUI RPC console even if external calls are disabled. */ diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 12f2fce22b..974156e6e1 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -6,7 +6,6 @@ #define BITCOIN_INTERFACES_NODE_H #include <consensus/amount.h> -#include <external_signer.h> #include <net.h> // For NodeId #include <net_types.h> // For banmap_t #include <netaddress.h> // For Network @@ -51,6 +50,16 @@ struct BlockAndHeaderTipInfo double verification_progress; }; +//! External signer interface used by the GUI. +class ExternalSigner +{ +public: + virtual ~ExternalSigner() {}; + + //! Get signer display name + virtual std::string getName() = 0; +}; + //! Top-level interface for a bitcoin node (bitcoind process). class Node { @@ -112,8 +121,8 @@ public: //! Disconnect node by id. virtual bool disconnectById(NodeId id) = 0; - //! List external signers - virtual std::vector<ExternalSigner> externalSigners() = 0; + //! Return list of external signers (attached devices which can sign transactions). + virtual std::vector<std::unique_ptr<ExternalSigner>> listExternalSigners() = 0; //! Get total bytes recv. virtual int64_t getTotalBytesRecv() = 0; @@ -201,6 +210,10 @@ public: using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>; virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0; + //! Register handler for wallet client constructed messages. + using InitWalletFn = std::function<void()>; + virtual std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) = 0; + //! Register handler for number of connections changed messages. using NotifyNumConnectionsChangedFn = std::function<void(int new_num_connections)>; virtual std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) = 0; diff --git a/src/key.cpp b/src/key.cpp index 7688254515..86081b3464 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -275,7 +275,7 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) return true; } -bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256* aux) const +bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const { assert(sig.size() == 64); secp256k1_keypair keypair; @@ -288,7 +288,7 @@ bool CKey::SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint2 uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root); if (!secp256k1_keypair_xonly_tweak_add(GetVerifyContext(), &keypair, tweak.data())) return false; } - bool ret = secp256k1_schnorrsig_sign(secp256k1_context_sign, sig.data(), hash.data(), &keypair, aux ? (unsigned char*)aux->data() : nullptr); + bool ret = secp256k1_schnorrsig_sign(secp256k1_context_sign, sig.data(), hash.data(), &keypair, (unsigned char*)aux.data()); if (ret) { // Additional verification step to prevent using a potentially corrupted signature secp256k1_xonly_pubkey pubkey_verify; @@ -130,7 +130,7 @@ public: /** * Create a BIP-340 Schnorr signature, for the xonly-pubkey corresponding to *this, - * optionally tweaked by *merkle_root. Additional nonce entropy can be provided through + * optionally tweaked by *merkle_root. Additional nonce entropy is provided through * aux. * * merkle_root is used to optionally perform tweaking of the private key, as specified @@ -143,7 +143,7 @@ public: * (this is used for key path spending, with specific * Merkle root of the script tree). */ - bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root = nullptr, const uint256* aux = nullptr) const; + bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const; //! Derive BIP32 child key. bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 57142e1c73..9c2d23f839 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -67,6 +67,17 @@ using interfaces::WalletClient; namespace node { namespace { +#ifdef ENABLE_EXTERNAL_SIGNER +class ExternalSignerImpl : public interfaces::ExternalSigner +{ +public: + ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {} + std::string getName() override { return m_signer.m_name; } +private: + ::ExternalSigner m_signer; +}; +#endif + class NodeImpl : public Node { private: @@ -172,14 +183,18 @@ public: } return false; } - std::vector<ExternalSigner> externalSigners() override + std::vector<std::unique_ptr<interfaces::ExternalSigner>> listExternalSigners() override { #ifdef ENABLE_EXTERNAL_SIGNER std::vector<ExternalSigner> signers = {}; const std::string command = gArgs.GetArg("-signer", ""); - if (command == "") return signers; + if (command == "") return {}; ExternalSigner::Enumerate(command, signers, Params().NetworkIDString()); - return signers; + std::vector<std::unique_ptr<interfaces::ExternalSigner>> result; + for (auto& signer : signers) { + result.emplace_back(std::make_unique<ExternalSignerImpl>(std::move(signer))); + } + return result; #else // This result is indistinguishable from a successful call that returns // no signers. For the current GUI this doesn't matter, because the wallet @@ -285,6 +300,10 @@ public: { return MakeHandler(::uiInterface.ShowProgress_connect(fn)); } + std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override + { + return MakeHandler(::uiInterface.InitWallet_connect(fn)); + } std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override { return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn)); diff --git a/src/node/ui_interface.cpp b/src/node/ui_interface.cpp index 8d3665975d..29fa16d8be 100644 --- a/src/node/ui_interface.cpp +++ b/src/node/ui_interface.cpp @@ -15,6 +15,7 @@ struct UISignals { boost::signals2::signal<CClientUIInterface::ThreadSafeMessageBoxSig, boost::signals2::optional_last_value<bool>> ThreadSafeMessageBox; boost::signals2::signal<CClientUIInterface::ThreadSafeQuestionSig, boost::signals2::optional_last_value<bool>> ThreadSafeQuestion; boost::signals2::signal<CClientUIInterface::InitMessageSig> InitMessage; + boost::signals2::signal<CClientUIInterface::InitWalletSig> InitWallet; boost::signals2::signal<CClientUIInterface::NotifyNumConnectionsChangedSig> NotifyNumConnectionsChanged; boost::signals2::signal<CClientUIInterface::NotifyNetworkActiveChangedSig> NotifyNetworkActiveChanged; boost::signals2::signal<CClientUIInterface::NotifyAlertChangedSig> NotifyAlertChanged; @@ -34,6 +35,7 @@ static UISignals g_ui_signals; ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeMessageBox); ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeQuestion); ADD_SIGNALS_IMPL_WRAPPER(InitMessage); +ADD_SIGNALS_IMPL_WRAPPER(InitWallet); ADD_SIGNALS_IMPL_WRAPPER(NotifyNumConnectionsChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkActiveChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyAlertChanged); @@ -45,6 +47,7 @@ ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged); bool CClientUIInterface::ThreadSafeMessageBox(const bilingual_str& message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style).value_or(false);} bool CClientUIInterface::ThreadSafeQuestion(const bilingual_str& message, const std::string& non_interactive_message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style).value_or(false);} void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_signals.InitMessage(message); } +void CClientUIInterface::InitWallet() { return g_ui_signals.InitWallet(); } void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); } void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); } void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); } diff --git a/src/node/ui_interface.h b/src/node/ui_interface.h index d574ab879f..f969bcde21 100644 --- a/src/node/ui_interface.h +++ b/src/node/ui_interface.h @@ -82,6 +82,9 @@ public: /** Progress message during initialization. */ ADD_SIGNALS_DECL_WRAPPER(InitMessage, void, const std::string& message); + /** Wallet client created. */ + ADD_SIGNALS_DECL_WRAPPER(InitWallet, void, ); + /** Number of network connections changed. */ ADD_SIGNALS_DECL_WRAPPER(NotifyNumConnectionsChanged, void, int newNumConnections); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 3f412d8f19..922aac531f 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -273,7 +273,6 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) // We don't hold a direct pointer to the splash screen after creation, but the splash // screen will take care of deleting itself when finish() happens. m_splash->show(); - connect(this, &BitcoinApplication::requestedInitialize, m_splash, &SplashScreen::handleLoadWallet); connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish); connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close); } diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp index f9a61c3e60..eba70331f8 100644 --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -6,7 +6,7 @@ #include <config/bitcoin-config.h> #endif -#include <external_signer.h> +#include <interfaces/node.h> #include <qt/createwalletdialog.h> #include <qt/forms/ui_createwalletdialog.h> @@ -113,7 +113,7 @@ CreateWalletDialog::~CreateWalletDialog() delete ui; } -void CreateWalletDialog::setSigners(const std::vector<ExternalSigner>& signers) +void CreateWalletDialog::setSigners(const std::vector<std::unique_ptr<interfaces::ExternalSigner>>& signers) { m_has_signers = !signers.empty(); if (m_has_signers) { @@ -126,7 +126,7 @@ void CreateWalletDialog::setSigners(const std::vector<ExternalSigner>& signers) ui->blank_wallet_checkbox->setChecked(false); ui->disable_privkeys_checkbox->setEnabled(false); ui->disable_privkeys_checkbox->setChecked(true); - const std::string label = signers[0].m_name; + const std::string label = signers[0]->getName(); ui->wallet_name_line_edit->setText(QString::fromStdString(label)); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } else { diff --git a/src/qt/createwalletdialog.h b/src/qt/createwalletdialog.h index fc13cc44eb..63a5e012d8 100644 --- a/src/qt/createwalletdialog.h +++ b/src/qt/createwalletdialog.h @@ -7,7 +7,12 @@ #include <QDialog> +#include <memory> + +namespace interfaces { class ExternalSigner; +} // namespace interfaces + class WalletModel; namespace Ui { @@ -24,7 +29,7 @@ public: explicit CreateWalletDialog(QWidget* parent); virtual ~CreateWalletDialog(); - void setSigners(const std::vector<ExternalSigner>& signers); + void setSigners(const std::vector<std::unique_ptr<interfaces::ExternalSigner>>& signers); QString walletName() const; bool isEncryptWalletChecked() const; diff --git a/src/qt/res/animation/makespinner.sh b/src/qt/res/animation/makespinner.sh index 83142f5034..647ee1aed8 100755 --- a/src/qt/res/animation/makespinner.sh +++ b/src/qt/res/animation/makespinner.sh @@ -5,10 +5,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. export LC_ALL=C -FRAMEDIR=$(dirname $0) +FRAMEDIR=$(dirname "$0") for i in {0..35} do - frame=$(printf "%03d" $i) + frame=$(printf "%03d" "$i") angle=$((i * 10)) - convert $FRAMEDIR/../src/spinner.png -background "rgba(0,0,0,0.0)" -distort SRT $angle $FRAMEDIR/spinner-$frame.png + convert "${FRAMEDIR}/../src/spinner.png" -background "rgba(0,0,0,0.0)" -distort SRT $angle "${FRAMEDIR}/spinner-${frame}.png" done diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 61b52fd08a..85703b3350 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -194,6 +194,7 @@ void SplashScreen::subscribeToCoreSignals() // Connect signals to client m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1)); m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + m_handler_init_wallet = m_node->handleInitWallet([this]() { handleLoadWallet(); }); } void SplashScreen::handleLoadWallet() diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 386039291c..8a5875d2a6 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -66,6 +66,7 @@ private: bool m_shutdown = false; std::unique_ptr<interfaces::Handler> m_handler_init_message; std::unique_ptr<interfaces::Handler> m_handler_show_progress; + std::unique_ptr<interfaces::Handler> m_handler_init_wallet; std::unique_ptr<interfaces::Handler> m_handler_load_wallet; std::list<std::unique_ptr<interfaces::Wallet>> m_connected_wallets; std::list<std::unique_ptr<interfaces::Handler>> m_connected_wallet_handlers; diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index a0ad59f12a..b9a9fcf3d1 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -280,9 +280,9 @@ void CreateWalletActivity::create() { m_create_wallet_dialog = new CreateWalletDialog(m_parent_widget); - std::vector<ExternalSigner> signers; + std::vector<std::unique_ptr<interfaces::ExternalSigner>> signers; try { - signers = node().externalSigners(); + signers = node().listExternalSigners(); } catch (const std::runtime_error& e) { QMessageBox::critical(nullptr, tr("Can't list signers"), e.what()); } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index eafa9840d7..d83ec7192b 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1483,7 +1483,7 @@ template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo, template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo); template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo); -static const CHashWriter HASHER_TAPSIGHASH = TaggedHash("TapSighash"); +const CHashWriter HASHER_TAPSIGHASH = TaggedHash("TapSighash"); const CHashWriter HASHER_TAPLEAF = TaggedHash("TapLeaf"); const CHashWriter HASHER_TAPBRANCH = TaggedHash("TapBranch"); diff --git a/src/script/interpreter.h b/src/script/interpreter.h index ab49e84577..513eaaf94c 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -229,6 +229,7 @@ static constexpr size_t TAPROOT_CONTROL_NODE_SIZE = 32; static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT = 128; static constexpr size_t TAPROOT_CONTROL_MAX_SIZE = TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT; +extern const CHashWriter HASHER_TAPSIGHASH; //!< Hasher with tag "TapSighash" pre-fed to it. extern const CHashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fed to it. extern const CHashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it. diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 4cb2125747..b282f39e6d 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -81,7 +81,8 @@ bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider& uint256 hash; if (!SignatureHashSchnorr(hash, execdata, *txTo, nIn, nHashType, sigversion, *m_txdata, MissingDataBehavior::FAIL)) return false; sig.resize(64); - if (!key.SignSchnorr(hash, sig, merkle_root, nullptr)) return false; + // Use uint256{} as aux_rnd for now. + if (!key.SignSchnorr(hash, sig, merkle_root, {})) return false; if (nHashType) sig.push_back(nHashType); return true; } diff --git a/src/test/data/bip341_wallet_vectors.json b/src/test/data/bip341_wallet_vectors.json new file mode 100644 index 0000000000..11261b00ba --- /dev/null +++ b/src/test/data/bip341_wallet_vectors.json @@ -0,0 +1,452 @@ +{ + "version": 1, + "scriptPubKey": [ + { + "given": { + "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d", + "scriptTree": null + }, + "intermediary": { + "merkleRoot": null, + "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70", + "tweakedPubkey": "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343" + }, + "expected": { + "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343", + "bip350Address": "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5" + } + }, + { + "given": { + "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "scriptTree": { + "id": 0, + "script": "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac", + "leafVersion": 192 + } + }, + "intermediary": { + "leafHashes": [ + "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21" + ], + "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001", + "tweakedPubkey": "147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3" + }, + "expected": { + "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "bip350Address": "bc1pz37fc4cn9ah8anwm4xqqhvxygjf9rjf2resrw8h8w4tmvcs0863sa2e586", + "scriptPathControlBlocks": [ + "c1187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27" + ] + } + }, + { + "given": { + "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820", + "scriptTree": { + "id": 0, + "script": "20b617298552a72ade070667e86ca63b8f5789a9fe8731ef91202a91c9f3459007ac", + "leafVersion": 192 + } + }, + "intermediary": { + "leafHashes": [ + "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b" + ], + "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b", + "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30", + "tweakedPubkey": "e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e" + }, + "expected": { + "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e", + "bip350Address": "bc1punvppl2stp38f7kwv2u2spltjuvuaayuqsthe34hd2dyy5w4g58qqfuag5", + "scriptPathControlBlocks": [ + "c093478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820" + ] + } + }, + { + "given": { + "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592", + "scriptTree": [ + { + "id": 0, + "script": "20387671353e273264c495656e27e39ba899ea8fee3bb69fb2a680e22093447d48ac", + "leafVersion": 192 + }, + { + "id": 1, + "script": "06424950333431", + "leafVersion": 250 + } + ] + }, + "intermediary": { + "leafHashes": [ + "8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7", + "f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a" + ], + "merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef", + "tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9", + "tweakedPubkey": "712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5" + }, + "expected": { + "scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5", + "bip350Address": "bc1pwyjywgrd0ffr3tx8laflh6228dj98xkjj8rum0zfpd6h0e930h6saqxrrm", + "scriptPathControlBlocks": [ + "c0ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a", + "faee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf37865928ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7" + ] + } + }, + { + "given": { + "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8", + "scriptTree": [ + { + "id": 0, + "script": "2044b178d64c32c4a05cc4f4d1407268f764c940d20ce97abfd44db5c3592b72fdac", + "leafVersion": 192 + }, + { + "id": 1, + "script": "07546170726f6f74", + "leafVersion": 192 + } + ] + }, + "intermediary": { + "leafHashes": [ + "64512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89", + "2cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb" + ], + "merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc", + "tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e", + "tweakedPubkey": "77e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220" + }, + "expected": { + "scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220", + "bip350Address": "bc1pwl3s54fzmk0cjnpl3w9af39je7pv5ldg504x5guk2hpecpg2kgsqaqstjq", + "scriptPathControlBlocks": [ + "c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd82cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb", + "c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd864512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89" + ] + } + }, + { + "given": { + "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f", + "scriptTree": [ + { + "id": 0, + "script": "2072ea6adcf1d371dea8fba1035a09f3d24ed5a059799bae114084130ee5898e69ac", + "leafVersion": 192 + }, + [ + { + "id": 1, + "script": "202352d137f2f3ab38d1eaa976758873377fa5ebb817372c71e2c542313d4abda8ac", + "leafVersion": 192 + }, + { + "id": 2, + "script": "207337c0dd4253cb86f2c43a2351aadd82cccb12a172cd120452b9bb8324f2186aac", + "leafVersion": 192 + } + ] + ] + }, + "intermediary": { + "leafHashes": [ + "2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817", + "ba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c", + "9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf6" + ], + "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2", + "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4", + "tweakedPubkey": "91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605" + }, + "expected": { + "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605", + "bip350Address": "bc1pjxmy65eywgafs5tsunw95ruycpqcqnev6ynxp7jaasylcgtcxczs6n332e", + "scriptPathControlBlocks": [ + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fffe578e9ea769027e4f5a3de40732f75a88a6353a09d767ddeb66accef85e553", + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf62645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817", + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817" + ] + } + }, + { + "given": { + "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d", + "scriptTree": [ + { + "id": 0, + "script": "2071981521ad9fc9036687364118fb6ccd2035b96a423c59c5430e98310a11abe2ac", + "leafVersion": 192 + }, + [ + { + "id": 1, + "script": "20d5094d2dbe9b76e2c245a2b89b6006888952e2faa6a149ae318d69e520617748ac", + "leafVersion": 192 + }, + { + "id": 2, + "script": "20c440b462ad48c7a77f94cd4532d8f2119dcebbd7c9764557e62726419b08ad4cac", + "leafVersion": 192 + } + ] + ] + }, + "intermediary": { + "leafHashes": [ + "f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d", + "737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711", + "d7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7" + ], + "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def", + "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9", + "tweakedPubkey": "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831" + }, + "expected": { + "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831", + "bip350Address": "bc1pw5tf7sqp4f50zka7629jrr036znzew70zxyvvej3zrpf8jg8hqcssyuewe", + "scriptPathControlBlocks": [ + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d3cd369a528b326bc9d2133cbd2ac21451acb31681a410434672c8e34fe757e91", + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312dd7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d", + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d" + ] + } + } + ], + "keyPathSpending": [ + { + "given": { + "rawUnsignedTx": "02000000097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a418420000000000fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0065cd1d", + "utxosSpent": [ + { + "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343", + "amountSats": 420000000 + }, + { + "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amountSats": 462000000 + }, + { + "scriptPubKey": "76a914751e76e8199196d454941c45d1b3a323f1433bd688ac", + "amountSats": 294000000 + }, + { + "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e", + "amountSats": 504000000 + }, + { + "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605", + "amountSats": 630000000 + }, + { + "scriptPubKey": "00147dd65592d0ab2fe0d0257d571abf032cd9db93dc", + "amountSats": 378000000 + }, + { + "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831", + "amountSats": 672000000 + }, + { + "scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5", + "amountSats": 546000000 + }, + { + "scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220", + "amountSats": 588000000 + } + ] + }, + "intermediary": { + "hashAmounts": "58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde6", + "hashOutputs": "a2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc5", + "hashPrevouts": "e3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f", + "hashScriptPubkeys": "23ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e21", + "hashSequences": "18959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e" + }, + "inputSpending": [ + { + "given": { + "txinIndex": 0, + "internalPrivkey": "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa", + "merkleRoot": null, + "hashType": 3 + }, + "intermediary": { + "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d", + "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70", + "tweakedPrivkey": "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9", + "sigMsg": "0003020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0000000000d0418f0e9a36245b9a50ec87f8bf5be5bcae434337b87139c3a5b1f56e33cba0", + "precomputedUsed": [ + "hashAmounts", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "2514a6272f85cfa0f45eb907fcb0d121b808ed37c6ea160a5a9046ed5526d555" + }, + "expected": { + "witness": [ + "ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c03" + ] + } + }, + { + "given": { + "txinIndex": 1, + "internalPrivkey": "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f", + "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "hashType": 131 + }, + "intermediary": { + "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001", + "tweakedPrivkey": "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080", + "sigMsg": "0083020000000065cd1d00d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd9900000000808f891b00000000225120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3ffffffffffcef8fb4ca7efc5433f591ecfc57391811ce1e186a3793024def5c884cba51d", + "precomputedUsed": [], + "sigHash": "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d" + }, + "expected": { + "witness": [ + "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83" + ] + } + }, + { + "given": { + "txinIndex": 3, + "internalPrivkey": "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64", + "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b", + "hashType": 1 + }, + "intermediary": { + "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820", + "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30", + "tweakedPrivkey": "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d", + "sigMsg": "0001020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50003000000", + "precomputedUsed": [ + "hashAmounts", + "hashOutputs", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "bf013ea93474aa67815b1b6cc441d23b64fa310911d991e713cd34c7f5d46669" + }, + "expected": { + "witness": [ + "ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a01" + ] + } + }, + { + "given": { + "txinIndex": 4, + "internalPrivkey": "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e", + "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2", + "hashType": 0 + }, + "intermediary": { + "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f", + "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4", + "tweakedPrivkey": "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501", + "sigMsg": "0000020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50004000000", + "precomputedUsed": [ + "hashAmounts", + "hashOutputs", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "4f900a0bae3f1446fd48490c2958b5a023228f01661cda3496a11da502a7f7ef" + }, + "expected": { + "witness": [ + "b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f" + ] + } + }, + { + "given": { + "txinIndex": 6, + "internalPrivkey": "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8", + "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def", + "hashType": 2 + }, + "intermediary": { + "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d", + "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9", + "tweakedPrivkey": "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901", + "sigMsg": "0002020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0006000000", + "precomputedUsed": [ + "hashAmounts", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "15f25c298eb5cdc7eb1d638dd2d45c97c4c59dcaec6679cfc16ad84f30876b85" + }, + "expected": { + "witness": [ + "a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee002" + ] + } + }, + { + "given": { + "txinIndex": 7, + "internalPrivkey": "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103", + "merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef", + "hashType": 130 + }, + "intermediary": { + "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592", + "tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9", + "tweakedPrivkey": "65b6000cd2bfa6b7cf736767a8955760e62b6649058cbc970b7c0871d786346b", + "sigMsg": "0082020000000065cd1d00e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf00000000804c8b2000000000225120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5ffffffff", + "precomputedUsed": [], + "sigHash": "cd292de50313804dabe4685e83f923d2969577191a3e1d2882220dca88cbeb10" + }, + "expected": { + "witness": [ + "ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c482" + ] + } + }, + { + "given": { + "txinIndex": 8, + "internalPrivkey": "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa", + "merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc", + "hashType": 129 + }, + "intermediary": { + "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8", + "tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e", + "tweakedPrivkey": "ec18ce6af99f43815db543f47b8af5ff5df3b2cb7315c955aa4a86e8143d2bf5", + "sigMsg": "0081020000000065cd1da2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc500a778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af101000000002b0c230000000022512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220ffffffff", + "precomputedUsed": [ + "hashOutputs" + ], + "sigHash": "cccb739eca6c13a8a89e6e5cd317ffe55669bbda23f2fd37b0f18755e008edd2" + }, + "expected": { + "witness": [ + "bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd981" + ] + } + } + ], + "auxiliary": { + "fullySignedTx": "020000000001097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a41842000000006b4830450221008f3b8f8f0537c420654d2283673a761b7ee2ea3c130753103e08ce79201cf32a022079e7ab904a1980ef1c5890b648c8783f4d10103dd62f740d13daa79e298d50c201210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0141ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c030141052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83000141ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a010140b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f0247304402202b795e4de72646d76eab3f0ab27dfa30b810e856ff3a46c9a702df53bb0d8cc302203ccc4d822edab5f35caddb10af1be93583526ccfbade4b4ead350781e2f8adcd012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f90141a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee0020141ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c4820141bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd9810065cd1d" + } + } + ] +} diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index c6df6a0e61..d427d12a3c 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -236,7 +236,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman) } } AddrManDeterministic& addr_man = *addr_man_ptr; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { @@ -247,7 +247,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman) }, [&] { std::vector<CAddress> addresses; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); if (!opt_address) { break; diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp index 479342e4be..0cc2d12d29 100644 --- a/src/test/fuzz/autofile.cpp +++ b/src/test/fuzz/autofile.cpp @@ -19,7 +19,7 @@ FUZZ_TARGET(autofile) FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider); CAutoFile auto_file = fuzzed_auto_file_provider.open(); - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp index 746591a176..3e303ecc0f 100644 --- a/src/test/fuzz/bloom_filter.cpp +++ b/src/test/fuzz/bloom_filter.cpp @@ -24,7 +24,7 @@ FUZZ_TARGET(bloom_filter) 1.0 / fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(1, std::numeric_limits<unsigned int>::max()), fuzzed_data_provider.ConsumeIntegral<unsigned int>(), static_cast<unsigned char>(fuzzed_data_provider.PickValueInArray({BLOOM_UPDATE_NONE, BLOOM_UPDATE_ALL, BLOOM_UPDATE_P2PUBKEY_ONLY, BLOOM_UPDATE_MASK}))}; - while (fuzzed_data_provider.remaining_bytes() > 0) { + LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp index ed72260d10..c3c2e4050f 100644 --- a/src/test/fuzz/buffered_file.cpp +++ b/src/test/fuzz/buffered_file.cpp @@ -29,7 +29,7 @@ FUZZ_TARGET(buffered_file) } if (opt_buffered_file && fuzzed_file != nullptr) { bool setpos_fail = false; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp index 9f7074b423..0e12a55408 100644 --- a/src/test/fuzz/chain.cpp +++ b/src/test/fuzz/chain.cpp @@ -35,7 +35,7 @@ FUZZ_TARGET(chain) (void)CDiskBlockIndex{*disk_block_index}; (void)disk_block_index->BuildSkip(); - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const BlockStatus block_status = fuzzed_data_provider.PickValueInArray({ BlockStatus::BLOCK_VALID_UNKNOWN, BlockStatus::BLOCK_VALID_RESERVED, diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 87e70861fa..325a9a170e 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -51,7 +51,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) COutPoint random_out_point; Coin random_coin; CMutableTransaction random_mutable_transaction; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { @@ -114,7 +114,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) }, [&] { CCoinsMap coins_map; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CCoinsCacheEntry coins_cache_entry; coins_cache_entry.flags = fuzzed_data_provider.ConsumeIntegral<unsigned char>(); if (fuzzed_data_provider.ConsumeBool()) { diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index d381345a0d..9e4718e603 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -31,7 +31,7 @@ FUZZ_TARGET_INIT(connman, initialize_connman) CNode random_node = ConsumeNode(fuzzed_data_provider); CSubNet random_subnet; std::string random_string; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/crypto_aes256.cpp b/src/test/fuzz/crypto_aes256.cpp index ccabd1f7dc..0937026fdd 100644 --- a/src/test/fuzz/crypto_aes256.cpp +++ b/src/test/fuzz/crypto_aes256.cpp @@ -19,7 +19,7 @@ FUZZ_TARGET(crypto_aes256) AES256Encrypt encrypt{key.data()}; AES256Decrypt decrypt{key.data()}; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::vector<uint8_t> plaintext = ConsumeFixedLengthByteVector(fuzzed_data_provider, AES_BLOCKSIZE); std::vector<uint8_t> ciphertext(AES_BLOCKSIZE); encrypt.Encrypt(ciphertext.data(), plaintext.data()); diff --git a/src/test/fuzz/crypto_aes256cbc.cpp b/src/test/fuzz/crypto_aes256cbc.cpp index 6d4138e546..5fe67bd4da 100644 --- a/src/test/fuzz/crypto_aes256cbc.cpp +++ b/src/test/fuzz/crypto_aes256cbc.cpp @@ -21,7 +21,7 @@ FUZZ_TARGET(crypto_aes256cbc) AES256CBCEncrypt encrypt{key.data(), iv.data(), pad}; AES256CBCDecrypt decrypt{key.data(), iv.data(), pad}; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::vector<uint8_t> plaintext = ConsumeRandomLengthByteVector(fuzzed_data_provider); std::vector<uint8_t> ciphertext(plaintext.size() + AES_BLOCKSIZE); const int encrypt_ret = encrypt.Encrypt(plaintext.data(), plaintext.size(), ciphertext.data()); diff --git a/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp index 8adfa92420..3f552a8cda 100644 --- a/src/test/fuzz/crypto_chacha20.cpp +++ b/src/test/fuzz/crypto_chacha20.cpp @@ -19,7 +19,7 @@ FUZZ_TARGET(crypto_chacha20) const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32)); chacha20 = ChaCha20{key.data(), key.size()}; } - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp index bb4ef22158..5e60b0f25b 100644 --- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp +++ b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp @@ -28,7 +28,7 @@ FUZZ_TARGET(crypto_chacha20_poly1305_aead) std::vector<uint8_t> in(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + POLY1305_TAGLEN, 0); std::vector<uint8_t> out(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + POLY1305_TAGLEN, 0); bool is_encrypt = fuzzed_data_provider.ConsumeBool(); - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp index 8cb9c55283..24bcc03dfd 100644 --- a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp +++ b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp @@ -18,7 +18,7 @@ FUZZ_TARGET(crypto_hkdf_hmac_sha256_l32) const std::vector<uint8_t> initial_key_material = ConsumeRandomLengthByteVector(fuzzed_data_provider); CHKDF_HMAC_SHA256_L32 hkdf_hmac_sha256_l32(initial_key_material.data(), initial_key_material.size(), fuzzed_data_provider.ConsumeRandomLengthString(1024)); - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { std::vector<uint8_t> out(32); hkdf_hmac_sha256_l32.Expand32(fuzzed_data_provider.ConsumeRandomLengthString(128), out.data()); } diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp index a522c837ef..019afe1c47 100644 --- a/src/test/fuzz/cuckoocache.cpp +++ b/src/test/fuzz/cuckoocache.cpp @@ -37,7 +37,7 @@ FUZZ_TARGET(cuckoocache) } else { cuckoo_cache.setup(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, 4096)); } - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { if (fuzzed_data_provider.ConsumeBool()) { cuckoo_cache.insert(fuzzed_data_provider.ConsumeBool()); } else { diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp index b5a07c7ba3..bcab66842c 100644 --- a/src/test/fuzz/fees.cpp +++ b/src/test/fuzz/fees.cpp @@ -18,7 +18,7 @@ FUZZ_TARGET(fees) FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)}; FeeFilterRounder fee_filter_rounder{minimal_incremental_fee}; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider); const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee); assert(MoneyRange(rounded_fee)); diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp index 1eefd4c521..6271367a9c 100644 --- a/src/test/fuzz/merkleblock.cpp +++ b/src/test/fuzz/merkleblock.cpp @@ -34,7 +34,7 @@ FUZZ_TARGET(merkleblock) if (fuzzed_data_provider.ConsumeBool()) { merkle_block = CMerkleBlock{*opt_block, bloom_filter}; } else if (fuzzed_data_provider.ConsumeBool()) { - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { txids.insert(ConsumeUInt256(fuzzed_data_provider)); } merkle_block = CMerkleBlock{*opt_block, txids}; diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index bd1bb79d0e..fb11ea36ce 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -32,7 +32,7 @@ FUZZ_TARGET_INIT(net, initialize_net) SetMockTime(ConsumeTime(fuzzed_data_provider)); CNode node{ConsumeNode(fuzzed_data_provider)}; node.SetCommonVersion(fuzzed_data_provider.ConsumeIntegral<int>()); - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/netbase_dns_lookup.cpp b/src/test/fuzz/netbase_dns_lookup.cpp index cf2fa33744..d01d413cff 100644 --- a/src/test/fuzz/netbase_dns_lookup.cpp +++ b/src/test/fuzz/netbase_dns_lookup.cpp @@ -22,7 +22,7 @@ FUZZ_TARGET(netbase_dns_lookup) auto fuzzed_dns_lookup_function = [&](const std::string&, bool) { std::vector<CNetAddr> resolved_addresses; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { resolved_addresses.push_back(ConsumeNetAddr(fuzzed_data_provider)); } return resolved_addresses; diff --git a/src/test/fuzz/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp index a3f71426fa..2e3b51e753 100644 --- a/src/test/fuzz/node_eviction.cpp +++ b/src/test/fuzz/node_eviction.cpp @@ -18,7 +18,7 @@ FUZZ_TARGET(node_eviction) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; std::vector<NodeEvictionCandidate> eviction_candidates; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { eviction_candidates.push_back({ /* id */ fuzzed_data_provider.ConsumeIntegral<NodeId>(), /* nTimeConnected */ fuzzed_data_provider.ConsumeIntegral<int64_t>(), diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp index 116b7a71d9..63dc4ce1d9 100644 --- a/src/test/fuzz/policy_estimator.cpp +++ b/src/test/fuzz/policy_estimator.cpp @@ -24,7 +24,7 @@ FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); CBlockPolicyEstimator block_policy_estimator; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { CallOneOf( fuzzed_data_provider, [&] { @@ -40,7 +40,7 @@ FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator) }, [&] { std::vector<CTxMemPoolEntry> mempool_entries; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider); if (!mtx) { break; diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index 47b4323e81..1123c8c170 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -27,7 +27,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow) std::vector<CBlockIndex> blocks; const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); - while (fuzzed_data_provider.remaining_bytes() > 0) { + LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 10000) { const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider); if (!block_header) { continue; diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index 11b236c9bd..91ec2aafde 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -55,7 +55,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) connman.AddTestNode(p2p_node); } - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; const auto mock_time = ConsumeTime(fuzzed_data_provider); diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp index 26c89a70c3..990bce5f6c 100644 --- a/src/test/fuzz/rbf.cpp +++ b/src/test/fuzz/rbf.cpp @@ -24,7 +24,7 @@ FUZZ_TARGET(rbf) return; } CTxMemPool pool; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::optional<CMutableTransaction> another_mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider); if (!another_mtx) { break; diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp index 9195cc4873..251687104e 100644 --- a/src/test/fuzz/rpc.cpp +++ b/src/test/fuzz/rpc.cpp @@ -294,7 +294,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider) std::string ConsumeArrayRPCArgument(FuzzedDataProvider& fuzzed_data_provider) { std::vector<std::string> scalar_arguments; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) { scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider)); } return "[\"" + Join(scalar_arguments, "\",\"") + "\"]"; @@ -348,7 +348,7 @@ FUZZ_TARGET_INIT(rpc, initialize_rpc) return; } std::vector<std::string> arguments; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) { arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider)); } try { diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index 74c576322a..0979967384 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -41,9 +41,7 @@ void initialize_script() FUZZ_TARGET_INIT(script, initialize_script) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - const std::optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider); - if (!script_opt) return; - const CScript script{*script_opt}; + const CScript script{ConsumeScript(fuzzed_data_provider)}; CompressedScript compressed; if (CompressScript(script, compressed)) { diff --git a/src/test/fuzz/script_descriptor_cache.cpp b/src/test/fuzz/script_descriptor_cache.cpp index 6ce13d5679..a90ad5e8ed 100644 --- a/src/test/fuzz/script_descriptor_cache.cpp +++ b/src/test/fuzz/script_descriptor_cache.cpp @@ -17,7 +17,7 @@ FUZZ_TARGET(script_descriptor_cache) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); DescriptorCache descriptor_cache; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::vector<uint8_t> code = fuzzed_data_provider.ConsumeBytes<uint8_t>(BIP32_EXTKEY_SIZE); if (code.size() == BIP32_EXTKEY_SIZE) { CExtPubKey xpub; diff --git a/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp index 4bc709ed35..12247679f2 100644 --- a/src/test/fuzz/script_ops.cpp +++ b/src/test/fuzz/script_ops.cpp @@ -15,7 +15,7 @@ FUZZ_TARGET(script_ops) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); CScript script_mut = ConsumeScript(fuzzed_data_provider); - while (fuzzed_data_provider.remaining_bytes() > 0) { + LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 1000000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/script_sign.cpp b/src/test/fuzz/script_sign.cpp index 684324c36e..79380bd9c9 100644 --- a/src/test/fuzz/script_sign.cpp +++ b/src/test/fuzz/script_sign.cpp @@ -48,7 +48,7 @@ FUZZ_TARGET_INIT(script_sign, initialize_script_sign) { std::map<CPubKey, KeyOriginInfo> hd_keypaths; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::optional<CPubKey> pub_key = ConsumeDeserializable<CPubKey>(fuzzed_data_provider); if (!pub_key) { break; @@ -125,7 +125,7 @@ FUZZ_TARGET_INIT(script_sign, initialize_script_sign) (void)signature_creator.CreateSig(provider, vch_sig, address, ConsumeScript(fuzzed_data_provider), fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0})); } std::map<COutPoint, Coin> coins; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { const std::optional<COutPoint> outpoint = ConsumeDeserializable<COutPoint>(fuzzed_data_provider); if (!outpoint) { break; diff --git a/src/test/fuzz/scriptnum_ops.cpp b/src/test/fuzz/scriptnum_ops.cpp index 62ed50d13f..0681aaf949 100644 --- a/src/test/fuzz/scriptnum_ops.cpp +++ b/src/test/fuzz/scriptnum_ops.cpp @@ -28,7 +28,7 @@ FUZZ_TARGET(scriptnum_ops) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider); - while (fuzzed_data_provider.remaining_bytes() > 0) { + LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 1000000) { CallOneOf( fuzzed_data_provider, [&] { diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp index 6b86c8889d..c3f416632d 100644 --- a/src/test/fuzz/signature_checker.cpp +++ b/src/test/fuzz/signature_checker.cpp @@ -58,8 +58,8 @@ FUZZ_TARGET_INIT(signature_checker, initialize_signature_checker) FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); - const auto script_1 = ConsumeScript(fuzzed_data_provider, 65536); - const auto script_2 = ConsumeScript(fuzzed_data_provider, 65536); + const auto script_1{ConsumeScript(fuzzed_data_provider)}; + const auto script_2{ConsumeScript(fuzzed_data_provider)}; std::vector<std::vector<unsigned char>> stack; (void)EvalScript(stack, script_1, flags, FuzzedSignatureChecker(fuzzed_data_provider), sig_version, nullptr); if (!IsValidFlagCombination(flags)) { diff --git a/src/test/fuzz/torcontrol.cpp b/src/test/fuzz/torcontrol.cpp index a97d3962bf..a78715f769 100644 --- a/src/test/fuzz/torcontrol.cpp +++ b/src/test/fuzz/torcontrol.cpp @@ -44,7 +44,7 @@ FUZZ_TARGET_INIT(torcontrol, initialize_torcontrol) FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; TorController tor_controller; - while (fuzzed_data_provider.ConsumeBool()) { + LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { TorControlReply tor_control_reply; CallOneOf( fuzzed_data_provider, diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp index d83d2924bb..ae5f7a379e 100644 --- a/src/test/fuzz/util.cpp +++ b/src/test/fuzz/util.cpp @@ -267,7 +267,7 @@ CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const auto amount = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-10, 50 * COIN + 10); const auto script_pk = p2wsh_op_true ? P2WSH_OP_TRUE : - ConsumeScript(fuzzed_data_provider, /* max_length */ 128, /* maybe_p2wsh */ true); + ConsumeScript(fuzzed_data_provider, /*maybe_p2wsh=*/true); tx_mut.vout.emplace_back(amount, script_pk); } return tx_mut; @@ -283,10 +283,63 @@ CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, co return ret; } -CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length, const bool maybe_p2wsh) noexcept +CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const bool maybe_p2wsh) noexcept { - const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); - CScript r_script{b.begin(), b.end()}; + CScript r_script{}; + { + // Keep a buffer of bytes to allow the fuzz engine to produce smaller + // inputs to generate CScripts with repeated data. + static constexpr unsigned MAX_BUFFER_SZ{128}; + std::vector<uint8_t> buffer(MAX_BUFFER_SZ, uint8_t{'a'}); + while (fuzzed_data_provider.ConsumeBool()) { + CallOneOf( + fuzzed_data_provider, + [&] { + // Insert byte vector directly to allow malformed or unparsable scripts + r_script.insert(r_script.end(), buffer.begin(), buffer.begin() + fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BUFFER_SZ)); + }, + [&] { + // Push a byte vector from the buffer + r_script << std::vector<uint8_t>{buffer.begin(), buffer.begin() + fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BUFFER_SZ)}; + }, + [&] { + // Push multisig + // There is a special case for this to aid the fuzz engine + // navigate the highly structured multisig format. + r_script << fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 22); + int num_data{fuzzed_data_provider.ConsumeIntegralInRange(1, 22)}; + std::vector<uint8_t> pubkey_comp{buffer.begin(), buffer.begin() + CPubKey::COMPRESSED_SIZE}; + pubkey_comp.front() = fuzzed_data_provider.ConsumeIntegralInRange(2, 3); // Set first byte for GetLen() to pass + std::vector<uint8_t> pubkey_uncomp{buffer.begin(), buffer.begin() + CPubKey::SIZE}; + pubkey_uncomp.front() = fuzzed_data_provider.ConsumeIntegralInRange(4, 7); // Set first byte for GetLen() to pass + while (num_data--) { + auto& pubkey{fuzzed_data_provider.ConsumeBool() ? pubkey_uncomp : pubkey_comp}; + if (fuzzed_data_provider.ConsumeBool()) { + pubkey.back() = num_data; // Make each pubkey different + } + r_script << pubkey; + } + r_script << fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 22); + }, + [&] { + // Mutate the buffer + const auto vec{ConsumeRandomLengthByteVector(fuzzed_data_provider, /*max_length=*/MAX_BUFFER_SZ)}; + std::copy(vec.begin(), vec.end(), buffer.begin()); + }, + [&] { + // Push an integral + r_script << fuzzed_data_provider.ConsumeIntegral<int64_t>(); + }, + [&] { + // Push an opcode + r_script << ConsumeOpcodeType(fuzzed_data_provider); + }, + [&] { + // Push a scriptnum + r_script << ConsumeScriptNum(fuzzed_data_provider); + }); + } + } if (maybe_p2wsh && fuzzed_data_provider.ConsumeBool()) { uint256 script_hash; CSHA256().Write(r_script.data(), r_script.size()).Finalize(script_hash.begin()); diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 1bc6f1db45..40aaeac63f 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -132,7 +132,7 @@ template <typename WeakEnumType, size_t size> [[nodiscard]] CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, const size_t max_stack_elem_size = 32) noexcept; -[[nodiscard]] CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length = std::nullopt, const bool maybe_p2wsh = false) noexcept; +[[nodiscard]] CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const bool maybe_p2wsh = false) noexcept; [[nodiscard]] uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept; diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp index 73a7d24971..cf95c0b9bf 100644 --- a/src/test/fuzz/versionbits.cpp +++ b/src/test/fuzz/versionbits.cpp @@ -199,7 +199,7 @@ FUZZ_TARGET_INIT(versionbits, initialize) const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); // mine prior periods - while (fuzzed_data_provider.remaining_bytes() > 0) { + while (fuzzed_data_provider.remaining_bytes() > 0) { // early exit; no need for LIMITED_WHILE // all blocks in these periods either do or don't signal bool signal = fuzzed_data_provider.ConsumeBool(); for (int b = 0; b < period; ++b) { diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index b915982d98..2769dde367 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -321,7 +321,7 @@ BOOST_AUTO_TEST_CASE(bip340_test_vectors) key.Set(sec.begin(), sec.end(), true); XOnlyPubKey pubkey(key.GetPubKey()); BOOST_CHECK(std::equal(pubkey.begin(), pubkey.end(), pub.begin(), pub.end())); - bool ok = key.SignSchnorr(msg256, sig64, nullptr, &aux256); + bool ok = key.SignSchnorr(msg256, sig64, nullptr, aux256); BOOST_CHECK(ok); BOOST_CHECK(std::vector<unsigned char>(sig64, sig64 + 64) == sig); // Verify those signatures for good measure. @@ -337,7 +337,7 @@ BOOST_AUTO_TEST_CASE(bip340_test_vectors) BOOST_CHECK(tweaked); XOnlyPubKey tweaked_key = tweaked->first; aux256 = InsecureRand256(); - bool ok = key.SignSchnorr(msg256, sig64, &merkle_root, &aux256); + bool ok = key.SignSchnorr(msg256, sig64, &merkle_root, aux256); BOOST_CHECK(ok); BOOST_CHECK(tweaked_key.VerifySchnorr(msg256, sig64)); } diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index bf8ff5f5e2..5a5cc6ab29 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -2,6 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <test/data/bip341_wallet_vectors.json.h> + #include <key.h> #include <key_io.h> #include <script/script.h> @@ -12,6 +14,8 @@ #include <boost/test/unit_test.hpp> +#include <univalue.h> + BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup) @@ -385,4 +389,46 @@ BOOST_AUTO_TEST_CASE(script_standard_taproot_builder) BOOST_CHECK_EQUAL(EncodeDestination(builder.GetOutput()), "bc1pj6gaw944fy0xpmzzu45ugqde4rz7mqj5kj0tg8kmr5f0pjq8vnaqgynnge"); } +BOOST_AUTO_TEST_CASE(bip341_spk_test_vectors) +{ + using control_set = decltype(TaprootSpendData::scripts)::mapped_type; + + UniValue tests; + tests.read((const char*)json_tests::bip341_wallet_vectors, sizeof(json_tests::bip341_wallet_vectors)); + + const auto& vectors = tests["scriptPubKey"]; + + for (const auto& vec : vectors.getValues()) { + TaprootBuilder spktest; + std::map<std::pair<CScript, int>, int> scriptposes; + std::function<void (const UniValue&, int)> parse_tree = [&](const UniValue& node, int depth) { + if (node.isNull()) return; + if (node.isObject()) { + auto script_bytes = ParseHex(node["script"].get_str()); + CScript script(script_bytes.begin(), script_bytes.end()); + int idx = node["id"].get_int(); + int leaf_version = node["leafVersion"].get_int(); + scriptposes[{script, leaf_version}] = idx; + spktest.Add(depth, script, leaf_version); + } else { + parse_tree(node[0], depth + 1); + parse_tree(node[1], depth + 1); + } + }; + parse_tree(vec["given"]["scriptTree"], 0); + spktest.Finalize(XOnlyPubKey(ParseHex(vec["given"]["internalPubkey"].get_str()))); + BOOST_CHECK_EQUAL(HexStr(GetScriptForDestination(spktest.GetOutput())), vec["expected"]["scriptPubKey"].get_str()); + BOOST_CHECK_EQUAL(EncodeDestination(spktest.GetOutput()), vec["expected"]["bip350Address"].get_str()); + auto spend_data = spktest.GetSpendData(); + BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].isNull(), spend_data.merkle_root.IsNull()); + if (!spend_data.merkle_root.IsNull()) { + BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].get_str(), HexStr(spend_data.merkle_root)); + } + BOOST_CHECK_EQUAL(spend_data.scripts.size(), scriptposes.size()); + for (const auto& scriptpos : scriptposes) { + BOOST_CHECK(spend_data.scripts[scriptpos.first] == control_set{ParseHex(vec["expected"]["scriptPathControlBlocks"][scriptpos.second].get_str())}); + } + } +} + BOOST_AUTO_TEST_SUITE_END() 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() diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp index 252832785b..e8b49f1220 100644 --- a/src/wallet/test/fuzz/notifications.cpp +++ b/src/wallet/test/fuzz/notifications.cpp @@ -100,7 +100,7 @@ FUZZ_TARGET_INIT(wallet_notifications, initialize_setup) using Coins = std::set<std::tuple<CAmount, COutPoint>>; std::vector<std::tuple<Coins, CBlock>> chain; { - // Add the inital entry + // Add the initial entry chain.emplace_back(); auto& [coins, block]{chain.back()}; coins.emplace(total_amount, COutPoint{uint256::ONE, 1}); diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index b609ba6881..d6717ebbca 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -26,7 +26,7 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag { LOCK(wallet_instance->cs_wallet); - wallet_instance->SetMinVersion(FEATURE_HD_SPLIT); + wallet_instance->SetMinVersion(FEATURE_LATEST); wallet_instance->AddWalletFlags(wallet_creation_flags); if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { |