| 105 | } |
| 106 | |
| 107 | std::optional<std::pair<int, std::vector<std::span<const unsigned char>>>> MatchMultiA(const CScript& script) |
| 108 | { |
| 109 | std::vector<std::span<const unsigned char>> keyspans; |
| 110 | |
| 111 | // Redundant, but very fast and selective test. |
| 112 | if (script.size() == 0 || script[0] != 32 || script.back() != OP_NUMEQUAL) return {}; |
| 113 | |
| 114 | // Parse keys |
| 115 | auto it = script.begin(); |
| 116 | while (script.end() - it >= 34) { |
| 117 | if (*it != 32) return {}; |
| 118 | ++it; |
| 119 | keyspans.emplace_back(&*it, 32); |
| 120 | it += 32; |
| 121 | if (*it != (keyspans.size() == 1 ? OP_CHECKSIG : OP_CHECKSIGADD)) return {}; |
| 122 | ++it; |
| 123 | } |
| 124 | if (keyspans.size() == 0 || keyspans.size() > MAX_PUBKEYS_PER_MULTI_A) return {}; |
| 125 | |
| 126 | // Parse threshold. |
| 127 | opcodetype opcode; |
| 128 | std::vector<unsigned char> data; |
| 129 | if (!script.GetOp(it, opcode, data)) return {}; |
| 130 | if (it == script.end()) return {}; |
| 131 | if (*it != OP_NUMEQUAL) return {}; |
| 132 | ++it; |
| 133 | if (it != script.end()) return {}; |
| 134 | auto threshold = GetScriptNumber(opcode, data, 1, (int)keyspans.size()); |
| 135 | if (!threshold) return {}; |
| 136 | |
| 137 | // Construct result. |
| 138 | return std::pair{*threshold, std::move(keyspans)}; |
| 139 | } |
| 140 | |
| 141 | TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet) |
| 142 | { |
no test coverage detected