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.
501default:502break;503}504return {};505}507/* This structure contains a table which for each "target" Type a list of recipes508* to construct it, automatically inferred from the behavior of ComputeType.509* Note that the Types here are not the final types of the constructed Nodes, but510* just the subset that are required. For example, a recipe for the "Bo" type511* might construct a "Bondu" sha256() NodeInfo, but cannot construct a "Bz" older().512* Each recipe is a Fragment together with a list of required types for its subnodes.513*/514struct SmartInfo515{516using recipe = std::pair<Fragment, std::vector<Type>>;517std::map<Type, std::vector<recipe>> wsh_table, tap_table;519void Init()520{521Init(wsh_table, MsCtx::P2WSH);522Init(tap_table, MsCtx::TAPSCRIPT);523}525void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)526{527/* Construct a set of interesting type requirements to reason with (sections of BKVWzondu). */528std::vector<Type> types;529for (int base = 0; base < 4; ++base) { /* select from B,K,V,W */530Type type_base = base == 0 ? "B"_mst : base == 1 ? "K"_mst : base == 2 ? "V"_mst : "W"_mst;531for (int zo = 0; zo < 3; ++zo) { /* select from z,o,(none) */532Type type_zo = zo == 0 ? "z"_mst : zo == 1 ? "o"_mst : ""_mst;533for (int n = 0; n < 2; ++n) { /* select from (none),n */534if (zo == 0 && n == 1) continue; /* z conflicts with n */535if (base == 3 && n == 1) continue; /* W conflicts with n */536Type type_n = n == 0 ? ""_mst : "n"_mst;537for (int d = 0; d < 2; ++d) { /* select from (none),d */538if (base == 2 && d == 1) continue; /* V conflicts with d */539Type type_d = d == 0 ? ""_mst : "d"_mst;540for (int u = 0; u < 2; ++u) { /* select from (none),u */541if (base == 2 && u == 1) continue; /* V conflicts with u */542Type type_u = u == 0 ? ""_mst : "u"_mst;543Type type = type_base | type_zo | type_n | type_d | type_u;544types.push_back(type);545}546}547}548}549}551/* We define a recipe a to be a super-recipe of recipe b if they use the same552* fragment, the same number of subexpressions, and each of a's subexpression553* types is a supertype of the corresponding subexpression type of b.554* Within the set of recipes for the construction of a given type requirement,555* no recipe should be a super-recipe of another (as the super-recipe is556* applicable in every place the sub-recipe is, the sub-recipe is redundant). */557auto is_super_of = [](const recipe& a, const recipe& b) {558if (a.first != b.first) return false;559if (a.second.size() != b.second.size()) return false;560for (size_t i = 0; i < a.second.size(); ++i) {561if (!(b.second[i] << a.second[i])) return false;562}563return true;564};566/* Sort the type requirements. Subtypes will always sort later (e.g. Bondu will567* sort after Bo or Bu). As we'll be constructing recipes using these types, in568* order, in what follows, we'll construct super-recipes before sub-recipes.569* That means we never need to go back and delete a sub-recipe because a570* super-recipe got added. */571std::sort(types.begin(), types.end());573// Iterate over all possible fragments.574for (int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {575int sub_count = 0; //!< The minimum number of child nodes this recipe has.576int sub_range = 1; //!< The maximum number of child nodes for this recipe is sub_count+sub_range-1.577size_t data_size = 0;578size_t n_keys = 0;579uint32_t k = 0;580Fragment frag{fragidx};582// Only produce recipes valid in the given context.583if ((!miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI_A)584|| (miniscript::IsTapscript(script_ctx) && frag == Fragment::MULTI)) {585continue;586}588// Based on the fragment, determine #subs/data/k/keys to pass to ComputeType. */589switch (frag) {590case Fragment::PK_K:591case Fragment::PK_H:592n_keys = 1;593break;594case Fragment::MULTI:595case Fragment::MULTI_A:596n_keys = 1;597k = 1;598break;599case Fragment::OLDER:600case Fragment::AFTER:601k = 1;602break;603case Fragment::SHA256:604case Fragment::HASH256:605data_size = 32;606break;607case Fragment::RIPEMD160:608case Fragment::HASH160:609data_size = 20;610break;611case Fragment::JUST_0:612case Fragment::JUST_1:613break;614case Fragment::WRAP_A:615case Fragment::WRAP_S:616case Fragment::WRAP_C:617case Fragment::WRAP_D:618case Fragment::WRAP_V:619case Fragment::WRAP_J:620case Fragment::WRAP_N:621sub_count = 1;622break;623case Fragment::AND_V:624case Fragment::AND_B:625case Fragment::OR_B:626case Fragment::OR_C:627case Fragment::OR_D:628case Fragment::OR_I:629sub_count = 2;630break;631case Fragment::ANDOR:632sub_count = 3;633break;634case Fragment::THRESH:635// Thresh logic is executed for 1 and 2 arguments. Larger numbers use ad-hoc code to extend.636sub_count = 1;637sub_range = 2;638k = 1;639break;640}642// Iterate over the number of subnodes (sub_count...sub_count+sub_range-1).643std::vector<Type> subt;644for (int subs = sub_count; subs < sub_count + sub_range; ++subs) {645// Iterate over the possible subnode types (at most 3).646for (Type x : types) {647for (Type y : types) {648for (Type z : types) {649// Compute the resulting type of a node with the selected fragment / subnode types.650subt.clear();651if (subs > 0) subt.push_back(x);652if (subs > 1) subt.push_back(y);653if (subs > 2) subt.push_back(z);654Type res = miniscript::internal::ComputeType(frag, x, y, z, subt, k, data_size, subs, n_keys, script_ctx);655// Continue if the result is not a valid node.656if ((res << "K"_mst) + (res << "V"_mst) + (res << "B"_mst) + (res << "W"_mst) != 1) continue;658recipe entry{frag, subt};659auto super_of_entry = [&](const recipe& rec) { return is_super_of(rec, entry); };660// Iterate over all supertypes of res (because if e.g. our selected fragment/subnodes result661// in a Bondu, they can form a recipe that is also applicable for constructing a B, Bou, Bdu, ...).662for (Type s : types) {663if ((res & "BKVWzondu"_mst) << s) {664auto& recipes = table[s];665// If we don't already have a super-recipe to the new one, add it.666if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {667recipes.push_back(entry);668}669}670}672if (subs <= 2) break;673}674if (subs <= 1) break;675}676if (subs <= 0) break;677}678}679}681/* Find which types are useful. The fuzzer logic only cares about constructing682* B,V,K,W nodes, so any type that isn't needed in any recipe (directly or683* indirectly) for the construction of those is uninteresting. */684std::set<Type> useful_types{"B"_mst, "V"_mst, "K"_mst, "W"_mst};685// Find the transitive closure by adding types until the set of types does not change.686while (true) {687size_t set_size = useful_types.size();688for (const auto& [type, recipes] : table) {689if (useful_types.contains(type)) {690for (const auto& [_, subtypes] : recipes) {691for (auto subtype : subtypes) useful_types.insert(subtype);692}693}694}695if (useful_types.size() == set_size) break;696}697// Remove all rules that construct uninteresting types.698for (auto type_it = table.begin(); type_it != table.end();) {699if (!useful_types.contains(type_it->first)) {700type_it = table.erase(type_it);701} else {702++type_it;703}704}706/* Find which types are constructible. A type is constructible if there is a leaf707* node recipe for constructing it, or a recipe whose subnodes are all constructible.708* Types can be non-constructible because they have no recipes to begin with,709* because they can only be constructed using recipes that involve otherwise710* non-constructible types, or because they require infinite recursion. */711std::set<Type> constructible_types{};712auto known_constructible = [&](Type type) { return constructible_types.contains(type); };713// Find the transitive closure by adding types until the set of types does not change.714while (true) {715size_t set_size = constructible_types.size();716// Iterate over all types we have recipes for.717for (const auto& [type, recipes] : table) {718if (!known_constructible(type)) {719// For not (yet known to be) constructible types, iterate over their recipes.720for (const auto& [_, subt] : recipes) {721// If any recipe involves only (already known to be) constructible types,722// add the recipe's type to the set.723if (std::all_of(subt.begin(), subt.end(), known_constructible)) {724constructible_types.insert(type);725break;726}727}728}729}730if (constructible_types.size() == set_size) break;731}732for (auto type_it = table.begin(); type_it != table.end();) {733// Remove all recipes which involve non-constructible types.734type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),735[&](const recipe& rec) {736return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);737}), type_it->second.end());738// Delete types entirely which have no recipes left.739if (type_it->second.empty()) {740type_it = table.erase(type_it);741} else {742++type_it;743}744}746for (auto& [type, recipes] : table) {747// Sort recipes for determinism, and place those using fewer subnodes first.748// This avoids runaway expansion (when reaching the end of the fuzz input,749// all zeroes are read, resulting in the first available recipe being picked).750std::sort(recipes.begin(), recipes.end(),
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.