aboutsummaryrefslogtreecommitdiff
path: root/src/script/standard.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2022-01-10 13:45:03 -0500
committerPieter Wuille <pieter@wuille.net>2022-01-12 11:09:41 -0500
commit79728c4a3d8a74f276daf1e72abbdecdab85a5d8 (patch)
treeca61b3411b91eb06f26919541ec4561f848197c3 /src/script/standard.cpp
parent25e95f9ff89a97b87ce218f28274c3c821b2d54d (diff)
downloadbitcoin-79728c4a3d8a74f276daf1e72abbdecdab85a5d8.tar.xz
Add (sorted)multi_a descriptor and script derivation
Diffstat (limited to 'src/script/standard.cpp')
-rw-r--r--src/script/standard.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 0dd8eba1ba..806b3169cd 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -139,6 +139,40 @@ static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector
return (it + 1 == script.end());
}
+std::optional<std::pair<int, std::vector<Span<const unsigned char>>>> MatchMultiA(const CScript& script)
+{
+ std::vector<Span<const unsigned char>> keyspans;
+
+ // Redundant, but very fast and selective test.
+ if (script.size() == 0 || script[0] != 32 || script.back() != OP_NUMEQUAL) return {};
+
+ // Parse keys
+ auto it = script.begin();
+ while (script.end() - it >= 34) {
+ if (*it != 32) return {};
+ ++it;
+ keyspans.emplace_back(&*it, 32);
+ it += 32;
+ if (*it != (keyspans.size() == 1 ? OP_CHECKSIG : OP_CHECKSIGADD)) return {};
+ ++it;
+ }
+ if (keyspans.size() == 0 || keyspans.size() > MAX_PUBKEYS_PER_MULTI_A) return {};
+
+ // Parse threshold.
+ opcodetype opcode;
+ std::vector<unsigned char> data;
+ if (!script.GetOp(it, opcode, data)) return {};
+ if (it == script.end()) return {};
+ if (*it != OP_NUMEQUAL) return {};
+ ++it;
+ if (it != script.end()) return {};
+ auto threshold = GetScriptNumber(opcode, data, 1, (int)keyspans.size());
+ if (!threshold) return {};
+
+ // Construct result.
+ return std::pair{*threshold, std::move(keyspans)};
+}
+
TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
{
vSolutionsRet.clear();