|
5 | 5 | #include <string>
|
6 | 6 | #include <vector>
|
7 | 7 | #include <script/script.h>
|
| 8 | +#include <script/standard.h> |
8 | 9 | #include <script/miniscript.h>
|
9 | 10 |
|
10 | 11 | #include <assert.h>
|
@@ -281,6 +282,58 @@ size_t ComputeScriptLen(Fragment nodetype, Type sub0typ, size_t subsize, uint32_
|
281 | 282 | return 0;
|
282 | 283 | }
|
283 | 284 |
|
| 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 | + |
284 | 337 | int FindNextChar(Span<const char> sp, const char m)
|
285 | 338 | {
|
286 | 339 | for (int i = 0; i < (int)sp.size(); ++i) {
|
|
0 commit comments