diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2019-09-01 19:31:22 -0700 |
---|---|---|
committer | Antoine Poinsot <darosior@protonmail.com> | 2022-03-17 14:09:08 +0100 |
commit | 2e55e88f86d0dd49b35d04af3f57e863498aabae (patch) | |
tree | e319e8942bf6c80d217f5a35ef8b46697a04c2fd /src/script/miniscript.cpp | |
parent | 1ddaa66eae67b102f5e37d212d366a5dcad4aa26 (diff) |
Miniscript: conversion from script
Co-Authored-By: Antoine Poinsot <darosior@protonmail.com>
Co-Authored-By: Samuel Dobson <dobsonsa68@gmail.com>
Diffstat (limited to 'src/script/miniscript.cpp')
-rw-r--r-- | src/script/miniscript.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/script/miniscript.cpp b/src/script/miniscript.cpp index 8074be6cde..d0bb937885 100644 --- a/src/script/miniscript.cpp +++ b/src/script/miniscript.cpp @@ -5,6 +5,7 @@ #include <string> #include <vector> #include <script/script.h> +#include <script/standard.h> #include <script/miniscript.h> #include <assert.h> @@ -281,6 +282,58 @@ size_t ComputeScriptLen(Fragment nodetype, Type sub0typ, size_t subsize, uint32_ return 0; } +bool DecomposeScript(const CScript& script, std::vector<std::pair<opcodetype, std::vector<unsigned char>>>& out) +{ + out.clear(); + CScript::const_iterator it = script.begin(), itend = script.end(); + while (it != itend) { + std::vector<unsigned char> push_data; + opcodetype opcode; + if (!script.GetOp(it, opcode, push_data)) { + out.clear(); + return false; + } else if (opcode >= OP_1 && opcode <= OP_16) { + // Deal with OP_n (GetOp does not turn them into pushes). + push_data.assign(1, CScript::DecodeOP_N(opcode)); + } else if (opcode == OP_CHECKSIGVERIFY) { + // Decompose OP_CHECKSIGVERIFY into OP_CHECKSIG OP_VERIFY + out.emplace_back(OP_CHECKSIG, std::vector<unsigned char>()); + opcode = OP_VERIFY; + } else if (opcode == OP_CHECKMULTISIGVERIFY) { + // Decompose OP_CHECKMULTISIGVERIFY into OP_CHECKMULTISIG OP_VERIFY + out.emplace_back(OP_CHECKMULTISIG, std::vector<unsigned char>()); + opcode = OP_VERIFY; + } else if (opcode == OP_EQUALVERIFY) { + // Decompose OP_EQUALVERIFY into OP_EQUAL OP_VERIFY + out.emplace_back(OP_EQUAL, std::vector<unsigned char>()); + opcode = OP_VERIFY; + } else if (IsPushdataOp(opcode)) { + if (!CheckMinimalPush(push_data, opcode)) return false; + } else if (it != itend && (opcode == OP_CHECKSIG || opcode == OP_CHECKMULTISIG || opcode == OP_EQUAL) && (*it == OP_VERIFY)) { + // Rule out non minimal VERIFY sequences + return false; + } + out.emplace_back(opcode, std::move(push_data)); + } + std::reverse(out.begin(), out.end()); + return true; +} + +bool ParseScriptNumber(const std::pair<opcodetype, std::vector<unsigned char>>& in, int64_t& k) { + if (in.first == OP_0) { + k = 0; + return true; + } + if (!in.second.empty()) { + if (IsPushdataOp(in.first) && !CheckMinimalPush(in.second, in.first)) return false; + try { + k = CScriptNum(in.second, true).GetInt64(); + return true; + } catch(const scriptnum_error&) {} + } + return false; +} + int FindNextChar(Span<const char> sp, const char m) { for (int i = 0; i < (int)sp.size(); ++i) { |