mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-11 06:28:31 +01:00
Merge/generalize IsValidMultisigKeyCount/GetMultisigKeyCount
This commit is contained in:
@@ -96,47 +96,45 @@ static constexpr bool IsPushdataOp(opcodetype opcode)
|
|||||||
return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
|
return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool IsValidMultisigKeyCount(int n_keys)
|
/** Retrieve a minimally-encoded number in range [min,max] from an (opcode, data) pair,
|
||||||
{
|
* whether it's OP_n or through a push. */
|
||||||
return n_keys > 0 && n_keys <= MAX_PUBKEYS_PER_MULTISIG;
|
static std::optional<int> GetScriptNumber(opcodetype opcode, valtype data, int min, int max)
|
||||||
}
|
|
||||||
|
|
||||||
static bool GetMultisigKeyCount(opcodetype opcode, valtype data, int& count)
|
|
||||||
{
|
{
|
||||||
|
int count;
|
||||||
if (IsSmallInteger(opcode)) {
|
if (IsSmallInteger(opcode)) {
|
||||||
count = CScript::DecodeOP_N(opcode);
|
count = CScript::DecodeOP_N(opcode);
|
||||||
return IsValidMultisigKeyCount(count);
|
} else if (IsPushdataOp(opcode)) {
|
||||||
}
|
if (!CheckMinimalPush(data, opcode)) return {};
|
||||||
|
|
||||||
if (IsPushdataOp(opcode)) {
|
|
||||||
if (!CheckMinimalPush(data, opcode)) return false;
|
|
||||||
try {
|
try {
|
||||||
count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
|
count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
|
||||||
return IsValidMultisigKeyCount(count);
|
|
||||||
} catch (const scriptnum_error&) {
|
} catch (const scriptnum_error&) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
if (count < min || count > max) return {};
|
||||||
return false;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
|
static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
|
||||||
{
|
{
|
||||||
opcodetype opcode;
|
opcodetype opcode;
|
||||||
valtype data;
|
valtype data;
|
||||||
int num_keys;
|
|
||||||
|
|
||||||
CScript::const_iterator it = script.begin();
|
CScript::const_iterator it = script.begin();
|
||||||
if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
|
if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
|
||||||
|
|
||||||
if (!script.GetOp(it, opcode, data) || !GetMultisigKeyCount(opcode, data, required_sigs)) return false;
|
if (!script.GetOp(it, opcode, data)) return false;
|
||||||
|
auto req_sigs = GetScriptNumber(opcode, data, 1, MAX_PUBKEYS_PER_MULTISIG);
|
||||||
|
if (!req_sigs) return false;
|
||||||
|
required_sigs = *req_sigs;
|
||||||
while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
|
while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
|
||||||
pubkeys.emplace_back(std::move(data));
|
pubkeys.emplace_back(std::move(data));
|
||||||
}
|
}
|
||||||
if (!GetMultisigKeyCount(opcode, data, num_keys)) return false;
|
auto num_keys = GetScriptNumber(opcode, data, required_sigs, MAX_PUBKEYS_PER_MULTISIG);
|
||||||
|
if (!num_keys) return false;
|
||||||
if (pubkeys.size() != static_cast<unsigned long>(num_keys) || num_keys < required_sigs) return false;
|
if (pubkeys.size() != static_cast<unsigned long>(*num_keys)) return false;
|
||||||
|
|
||||||
return (it + 1 == script.end());
|
return (it + 1 == script.end());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user