MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / DecodeScript

Function DecodeScript

src/script/miniscript.h:2298–2682  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2296//! Parse a miniscript from a bitcoin script
2297template <typename Key, typename Ctx, typename I>
2298inline std::optional<Node<Key>> DecodeScript(I& in, I last, const Ctx& ctx)
2299{
2300 // The two integers are used to hold state for thresh()
2301 std::vector<std::tuple<DecodeContext, int64_t, int64_t>> to_parse;
2302 std::vector<Node<Key>> constructed;
2303
2304 // This is the top level, so we assume the type is B
2305 // (in particular, disallowing top level W expressions)
2306 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2307
2308 while (!to_parse.empty()) {
2309 // Exit early if the Miniscript is not going to be valid.
2310 if (!constructed.empty() && !constructed.back().IsValid()) return {};
2311
2312 // Get the current context we are decoding within
2313 auto [cur_context, n, k] = to_parse.back();
2314 to_parse.pop_back();
2315
2316 switch(cur_context) {
2317 case DecodeContext::SINGLE_BKV_EXPR: {
2318 if (in >= last) return {};
2319
2320 // Constants
2321 if (in[0].first == OP_1) {
2322 ++in;
2323 constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_1);
2324 break;
2325 }
2326 if (in[0].first == OP_0) {
2327 ++in;
2328 constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::JUST_0);
2329 break;
2330 }
2331 // Public keys
2332 if (in[0].second.size() == 33 || in[0].second.size() == 32) {
2333 auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());
2334 if (!key) return {};
2335 ++in;
2336 constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_K, Vector(std::move(*key)));
2337 break;
2338 }
2339 if (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) {
2340 auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end());
2341 if (!key) return {};
2342 in += 5;
2343 constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::PK_H, Vector(std::move(*key)));
2344 break;
2345 }
2346 // Time locks
2347 std::optional<int64_t> num;
2348 if (last - in >= 2 && in[0].first == OP_CHECKSEQUENCEVERIFY && (num = ParseScriptNumber(in[1]))) {
2349 in += 2;
2350 if (*num < 1 || *num > 0x7FFFFFFFL) return {};
2351 constructed.emplace_back(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num);
2352 break;
2353 }
2354 if (last - in >= 2 && in[0].first == OP_CHECKLOCKTIMEVERIFY && (num = ParseScriptNumber(in[1]))) {
2355 in += 2;

Callers

nothing calls this directly

Calls 15

VectorFunction · 0.85
ParseScriptNumberFunction · 0.85
IsTapscriptFunction · 0.85
BuildBackFunction · 0.85
DuplicateKeyCheckMethod · 0.80
IsValidTopLevelMethod · 0.80
emplace_backMethod · 0.45
emptyMethod · 0.45
IsValidMethod · 0.45
backMethod · 0.45
pop_backMethod · 0.45
MsContextMethod · 0.45

Tested by

no test coverage detected