diff options
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) { |