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.
2251/** ZERO_NOTEQUAL wraps the top constructed node with n: */2252ZERO_NOTEQUAL,2254/** MAYBE_AND_V will check if the next part of the script could be a valid2255* miniscript sub-expression, and if so it will push AND_V and SINGLE_BKV_EXPR2256* to decode it and construct the and_v node. This is recursive, to deal with2257* multiple and_v nodes inside each other. */2258MAYBE_AND_V,2259/** AND_V will construct an and_v node from the last two constructed nodes. */2260AND_V,2261/** AND_B will construct an and_b node from the last two constructed nodes. */2262AND_B,2263/** ANDOR will construct an andor node from the last three constructed nodes. */2264ANDOR,2265/** OR_B will construct an or_b node from the last two constructed nodes. */2266OR_B,2267/** OR_C will construct an or_c node from the last two constructed nodes. */2268OR_C,2269/** OR_D will construct an or_d node from the last two constructed nodes. */2270OR_D,2272/** In a thresh expression, all sub-expressions other than the first are W-type,2273* and end in OP_ADD. THRESH_W will check for this OP_ADD and either push a W_EXPR2274* or a SINGLE_BKV_EXPR and jump to THRESH_E accordingly. */2275THRESH_W,2276/** THRESH_E constructs a thresh node from the appropriate number of constructed2277* children. */2278THRESH_E,2280/** ENDIF signals that we are inside some sort of OP_IF structure, which could be2281* or_d, or_c, or_i, andor, d:, or j: wrapper, depending on what follows. We read2282* a BKV_EXPR and then deal with the next opcode case-by-case. */2283ENDIF,2284/** If, inside an ENDIF context, we find an OP_NOTIF before finding an OP_ELSE,2285* we could either be in an or_d or an or_c node. We then check for IFDUP to2286* distinguish these cases. */2287ENDIF_NOTIF,2288/** If, inside an ENDIF context, we find an OP_ELSE, then we could be in either an2289* or_i or an andor node. Read the next BKV_EXPR and find either an OP_IF or an2290* OP_NOTIF. */2291ENDIF_ELSE,2292};2294//! Parse a miniscript from a bitcoin script2295template <typename Key, typename Ctx, typename I>2296inline std::optional<Node<Key>> DecodeScript(I& in, I last, const Ctx& ctx)2297{2298// The two integers are used to hold state for thresh()2299std::vector<std::tuple<DecodeContext, int64_t, int64_t>> to_parse;2300std::vector<Node<Key>> constructed;2302// This is the top level, so we assume the type is B2303// (in particular, disallowing top level W expressions)2304to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);2306while (!to_parse.empty()) {2307// Exit early if the Miniscript is not going to be valid.2308if (!constructed.empty() && !constructed.back().IsValid()) return {};2310// Get the current context we are decoding within2311auto [cur_context, n, k] = to_parse.back();2312to_parse.pop_back();2314switch(cur_context) {2315case DecodeContext::SINGLE_BKV_EXPR: {2316if (in >= last) return {};2318// Constants2319if (in[0].first == OP_1) {2320++in;2321constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1);2322break;2323}2324if (in[0].first == OP_0) {2325++in;2326constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0);2327break;2328}2329// Public keys2330if (in[0].second.size() == 33 || in[0].second.size() == 32) {2331auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());2332if (!key) return {};2333++in;2334constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(*key)));2335break;2336}2337if (last - in >= 5 && in[0].first == OP_VERIFY && in[1].first == OP_EQUAL && in[3].first == OP_HASH160 && in[4].first == OP_DUP && in[2].second.size() == 20) {2338auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end());2339if (!key) return {};2340in += 5;2341constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(*key)));2342break;2343}2344// Time locks2345std::optional<int64_t> num;2346if (last - in >= 2 && in[0].first == OP_CHECKSEQUENCEVERIFY && (num = ParseScriptNumber(in[1]))) {2347in += 2;2348if (*num < 1 || *num > 0x7FFFFFFFL) return {};2349constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num);2350break;2351}2352if (last - in >= 2 && in[0].first == OP_CHECKLOCKTIMEVERIFY && (num = ParseScriptNumber(in[1]))) {2353in += 2;2354if (num < 1 || num > 0x7FFFFFFFL) return {};2355constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num);2356break;2357}2358// Hashes2359if (last - in >= 7 && in[0].first == OP_EQUAL && in[3].first == OP_VERIFY && in[4].first == OP_EQUAL && (num = ParseScriptNumber(in[5])) && num == 32 && in[6].first == OP_SIZE) {2360if (in[2].first == OP_SHA256 && in[1].second.size() == 32) {2361constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::SHA256, in[1].second);2362in += 7;2363break;2364} else if (in[2].first == OP_RIPEMD160 && in[1].second.size() == 20) {2365constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, in[1].second);2366in += 7;2367break;2368} else if (in[2].first == OP_HASH256 && in[1].second.size() == 32) {2369constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, in[1].second);2370in += 7;2371break;2372} else if (in[2].first == OP_HASH160 && in[1].second.size() == 20) {2373constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, in[1].second);2374in += 7;2375break;2376}2377}2378// Multi2379if (last - in >= 3 && in[0].first == OP_CHECKMULTISIG) {2380if (IsTapscript(ctx.MsContext())) return {};2381std::vector<Key> keys;2382const auto n = ParseScriptNumber(in[1]);2383if (!n || last - in < 3 + *n) return {};2384if (*n < 1 || *n > 20) return {};2385for (int i = 0; i < *n; ++i) {2386if (in[2 + i].second.size() != 33) return {};2387auto key = ctx.FromPKBytes(in[2 + i].second.begin(), in[2 + i].second.end());2388if (!key) return {};2389keys.push_back(std::move(*key));2390}2391const auto k = ParseScriptNumber(in[2 + *n]);2392if (!k || *k < 1 || *k > *n) return {};2393in += 3 + *n;2394std::reverse(keys.begin(), keys.end());2395constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI, std::move(keys), *k);2396break;2397}2398// Tapscript's equivalent of multi2399if (last - in >= 4 && in[0].first == OP_NUMEQUAL) {2400if (!IsTapscript(ctx.MsContext())) return {};2401// The necessary threshold of signatures.2402const auto k = ParseScriptNumber(in[1]);2403if (!k) return {};2404if (*k < 1 || *k > MAX_PUBKEYS_PER_MULTI_A) return {};2405if (last - in < 2 + *k * 2) return {};2406std::vector<Key> keys;2407keys.reserve(*k);2408// Walk through the expected (pubkey, CHECKSIG[ADD]) pairs.2409for (int pos = 2;; pos += 2) {2410if (last - in < pos + 2) return {};2411// Make sure it's indeed an x-only pubkey and a CHECKSIG[ADD], then parse the key.2412if (in[pos].first != OP_CHECKSIGADD && in[pos].first != OP_CHECKSIG) return {};2413if (in[pos + 1].second.size() != 32) return {};2414auto key = ctx.FromPKBytes(in[pos + 1].second.begin(), in[pos + 1].second.end());2415if (!key) return {};2416keys.push_back(std::move(*key));2417// Make sure early we don't parse an arbitrary large expression.2418if (keys.size() > MAX_PUBKEYS_PER_MULTI_A) return {};2419// OP_CHECKSIG means it was the last one to parse.2420if (in[pos].first == OP_CHECKSIG) break;2421}2422if (keys.size() < (size_t)*k) return {};2423in += 2 + keys.size() * 2;2424std::reverse(keys.begin(), keys.end());2425constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::MULTI_A, std::move(keys), *k);2426break;2427}2428/** In the following wrappers, we only need to push SINGLE_BKV_EXPR rather2429* than BKV_EXPR, because and_v commutes with these wrappers. For example,2430* c:and_v(X,Y) produces the same script as and_v(X,c:Y). */2431// c: wrapper2432if (in[0].first == OP_CHECKSIG) {2433++in;2434to_parse.emplace_back(DecodeContext::CHECK, -1, -1);2435to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2436break;2437}2438// v: wrapper2439if (in[0].first == OP_VERIFY) {2440++in;2441to_parse.emplace_back(DecodeContext::VERIFY, -1, -1);2442to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2443break;2444}2445// n: wrapper2446if (in[0].first == OP_0NOTEQUAL) {2447++in;2448to_parse.emplace_back(DecodeContext::ZERO_NOTEQUAL, -1, -1);2449to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2450break;2451}2452// Thresh2453if (last - in >= 3 && in[0].first == OP_EQUAL && (num = ParseScriptNumber(in[1]))) {2454if (*num < 1) return {};2455in += 2;2456to_parse.emplace_back(DecodeContext::THRESH_W, 0, *num);2457break;2458}2459// OP_ENDIF can be WRAP_J, WRAP_D, ANDOR, OR_C, OR_D, or OR_I2460if (in[0].first == OP_ENDIF) {2461++in;2462to_parse.emplace_back(DecodeContext::ENDIF, -1, -1);2463to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);2464break;2465}2466/** In and_b and or_b nodes, we only look for SINGLE_BKV_EXPR, because2467* or_b(and_v(X,Y),Z) has script [X] [Y] [Z] OP_BOOLOR, the same as2468* and_v(X,or_b(Y,Z)). In this example, the former of these is invalid as2469* miniscript, while the latter is valid. So we leave the and_v "outside"2470* while decoding. */2471// and_b2472if (in[0].first == OP_BOOLAND) {2473++in;2474to_parse.emplace_back(DecodeContext::AND_B, -1, -1);2475to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2476to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);2477break;2478}2479// or_b2480if (in[0].first == OP_BOOLOR) {2481++in;2482to_parse.emplace_back(DecodeContext::OR_B, -1, -1);2483to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2484to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);2485break;2486}2487// Unrecognised expression2488return {};2489}2490case DecodeContext::BKV_EXPR: {2491to_parse.emplace_back(DecodeContext::MAYBE_AND_V, -1, -1);2492to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);2493break;2494}2495case DecodeContext::W_EXPR: {2496// a: wrapper2497if (in >= last) return {};2498if (in[0].first == OP_FROMALTSTACK) {2499++in;2500to_parse.emplace_back(DecodeContext::ALT, -1, -1);
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.