Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <chainparams.h>6#include <key_io.h>7#include <pubkey.h>8#include <script/descriptor.h>9#include <test/fuzz/fuzz.h>10#include <test/fuzz/util/descriptor.h>11#include <util/chaintype.h>12#include <util/strencodings.h>14//! The converter of mocked descriptors, needs to be initialized when the target is.15MockedDescriptorConverter MOCKED_DESC_CONVERTER;17/** Test a successfully parsed descriptor. */18static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy, std::optional<bool>& is_ranged, std::optional<bool>& is_solvable)19{20// Trivial helpers.21(void)desc.IsRange();22(void)desc.IsSingleType();23(void)desc.GetOutputType();25if (is_ranged.has_value()) {26assert(desc.IsRange() == *is_ranged);27} else {28is_ranged = desc.IsRange();29}30if (is_solvable.has_value()) {31assert(desc.IsSolvable() == *is_solvable);32} else {33is_solvable = desc.IsSolvable();34}36// Serialization to string representation.37(void)desc.ToString();38(void)desc.ToPrivateString(sig_provider, dummy);39(void)desc.ToNormalizedString(sig_provider, dummy);41// Serialization to Script.42DescriptorCache cache;43std::vector<CScript> out_scripts;44(void)desc.Expand(0, sig_provider, out_scripts, sig_provider, &cache);45(void)desc.ExpandPrivate(0, sig_provider, sig_provider);46(void)desc.ExpandFromCache(0, cache, out_scripts, sig_provider);48// If we could serialize to script we must be able to infer using the same provider.49if (!out_scripts.empty()) {50assert(InferDescriptor(out_scripts.back(), sig_provider));52// The ScriptSize() must match the size of the serialized Script. (ScriptSize() is set for all descs but 'combo()'.)53const bool is_combo{!desc.IsSingleType()};54assert(is_combo || desc.ScriptSize() == out_scripts.back().size());55}57const auto max_sat_maxsig{desc.MaxSatisfactionWeight(true)};58const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(false)};59// Whether an estimate is available must not depend on the signature-size60// assumption, and assuming non-max-size signatures must never increase it.61assert(max_sat_maxsig.has_value() == max_sat_nonmaxsig.has_value());62assert(max_sat_nonmaxsig <= max_sat_maxsig);63const auto max_elems{desc.MaxSatisfactionElems()};64// We must be able to estimate the max satisfaction size for any solvable descriptor (but combo).65const bool is_nontop_or_nonsolvable{!*is_solvable || !desc.GetOutputType()};66const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems};67assert(is_input_size_info_set || is_nontop_or_nonsolvable);69auto max_key_expr = desc.GetMaxKeyExpr();70auto key_count = desc.GetKeyCount();71assert((max_key_expr == 0 && key_count == 0) || max_key_expr + 1 == key_count);72}74void initialize_descriptor_parse()75{76static ECC_Context ecc_context{};77SelectParams(ChainType::MAIN);78}80void initialize_mocked_descriptor_parse()81{82initialize_descriptor_parse();83MOCKED_DESC_CONVERTER.Init();84}86FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse)87{88const std::string mocked_descriptor{buffer.begin(), buffer.end()};89if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) {90if (IsTooExpensive(MakeUCharSpan(*descriptor))) return;91FlatSigningProvider signing_provider;92std::string error;93const auto desc = Parse(*descriptor, signing_provider, error);94std::optional<bool> is_ranged;95std::optional<bool> is_solvable;96for (const auto& d : desc) {97assert(d);98TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);99}100}101}103FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse)104{105if (IsTooExpensive(buffer)) return;107const std::string descriptor(buffer.begin(), buffer.end());108FlatSigningProvider signing_provider;109std::string error;110for (const bool require_checksum : {true, false}) {111const auto desc = Parse(descriptor, signing_provider, error, require_checksum);112std::optional<bool> is_ranged;113std::optional<bool> is_solvable;114for (const auto& d : desc) {115assert(d);116TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);117}118}119}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.