Skip to content

Commit 2e55e88

Browse files
sipadarosiormeshcollider
committed
Miniscript: conversion from script
Co-Authored-By: Antoine Poinsot <[email protected]> Co-Authored-By: Samuel Dobson <[email protected]>
1 parent 1ddaa66 commit 2e55e88

File tree

3 files changed

+534
-0
lines changed

3 files changed

+534
-0
lines changed

src/script/miniscript.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <string>
66
#include <vector>
77
#include <script/script.h>
8+
#include <script/standard.h>
89
#include <script/miniscript.h>
910

1011
#include <assert.h>
@@ -281,6 +282,58 @@ size_t ComputeScriptLen(Fragment nodetype, Type sub0typ, size_t subsize, uint32_
281282
return 0;
282283
}
283284

285+
bool DecomposeScript(const CScript& script, std::vector<std::pair<opcodetype, std::vector<unsigned char>>>& out)
286+
{
287+
out.clear();
288+
CScript::const_iterator it = script.begin(), itend = script.end();
289+
while (it != itend) {
290+
std::vector<unsigned char> push_data;
291+
opcodetype opcode;
292+
if (!script.GetOp(it, opcode, push_data)) {
293+
out.clear();
294+
return false;
295+
} else if (opcode >= OP_1 && opcode <= OP_16) {
296+
// Deal with OP_n (GetOp does not turn them into pushes).
297+
push_data.assign(1, CScript::DecodeOP_N(opcode));
298+
} else if (opcode == OP_CHECKSIGVERIFY) {
299+
// Decompose OP_CHECKSIGVERIFY into OP_CHECKSIG OP_VERIFY
300+
out.emplace_back(OP_CHECKSIG, std::vector<unsigned char>());
301+
opcode = OP_VERIFY;
302+
} else if (opcode == OP_CHECKMULTISIGVERIFY) {
303+
// Decompose OP_CHECKMULTISIGVERIFY into OP_CHECKMULTISIG OP_VERIFY
304+
out.emplace_back(OP_CHECKMULTISIG, std::vector<unsigned char>());
305+
opcode = OP_VERIFY;
306+
} else if (opcode == OP_EQUALVERIFY) {
307+
// Decompose OP_EQUALVERIFY into OP_EQUAL OP_VERIFY
308+
out.emplace_back(OP_EQUAL, std::vector<unsigned char>());
309+
opcode = OP_VERIFY;
310+
} else if (IsPushdataOp(opcode)) {
311+
if (!CheckMinimalPush(push_data, opcode)) return false;
312+
} else if (it != itend && (opcode == OP_CHECKSIG || opcode == OP_CHECKMULTISIG || opcode == OP_EQUAL) && (*it == OP_VERIFY)) {
313+
// Rule out non minimal VERIFY sequences
314+
return false;
315+
}
316+
out.emplace_back(opcode, std::move(push_data));
317+
}
318+
std::reverse(out.begin(), out.end());
319+
return true;
320+
}
321+
322+
bool ParseScriptNumber(const std::pair<opcodetype, std::vector<unsigned char>>& in, int64_t& k) {
323+
if (in.first == OP_0) {
324+
k = 0;
325+
return true;
326+
}
327+
if (!in.second.empty()) {
328+
if (IsPushdataOp(in.first) && !CheckMinimalPush(in.second, in.first)) return false;
329+
try {
330+
k = CScriptNum(in.second, true).GetInt64();
331+
return true;
332+
} catch(const scriptnum_error&) {}
333+
}
334+
return false;
335+
}
336+
284337
int FindNextChar(Span<const char> sp, const char m)
285338
{
286339
for (int i = 0; i < (int)sp.size(); ++i) {

0 commit comments

Comments
 (0)