mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
Merge 60132382a7 into merged_master (Bitcoin PR bitcoin/bitcoin#20867)
This commit is contained in:
commit
fb60da4597
6 changed files with 168 additions and 21 deletions
|
|
@ -102,21 +102,53 @@ static constexpr bool IsSmallInteger(opcodetype opcode)
|
|||
return opcode >= OP_1 && opcode <= OP_16;
|
||||
}
|
||||
|
||||
static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
|
||||
static constexpr bool IsPushdataOp(opcodetype opcode)
|
||||
{
|
||||
return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
|
||||
}
|
||||
|
||||
static constexpr bool IsValidMultisigKeyCount(int n_keys)
|
||||
{
|
||||
return n_keys > 0 && n_keys <= MAX_PUBKEYS_PER_MULTISIG;
|
||||
}
|
||||
|
||||
static bool GetMultisigKeyCount(opcodetype opcode, valtype data, int& count)
|
||||
{
|
||||
if (IsSmallInteger(opcode)) {
|
||||
count = CScript::DecodeOP_N(opcode);
|
||||
return IsValidMultisigKeyCount(count);
|
||||
}
|
||||
|
||||
if (IsPushdataOp(opcode)) {
|
||||
if (!CheckMinimalPush(data, opcode)) return false;
|
||||
try {
|
||||
count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
|
||||
return IsValidMultisigKeyCount(count);
|
||||
} catch (const scriptnum_error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
|
||||
{
|
||||
opcodetype opcode;
|
||||
valtype data;
|
||||
int num_keys;
|
||||
|
||||
CScript::const_iterator it = script.begin();
|
||||
if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
|
||||
|
||||
if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
|
||||
required = CScript::DecodeOP_N(opcode);
|
||||
if (!script.GetOp(it, opcode, data) || !GetMultisigKeyCount(opcode, data, required_sigs)) return false;
|
||||
while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
|
||||
pubkeys.emplace_back(std::move(data));
|
||||
}
|
||||
if (!IsSmallInteger(opcode)) return false;
|
||||
unsigned int keys = CScript::DecodeOP_N(opcode);
|
||||
if (pubkeys.size() != keys || keys < required) return false;
|
||||
if (!GetMultisigKeyCount(opcode, data, num_keys)) return false;
|
||||
|
||||
if (pubkeys.size() != static_cast<unsigned long>(num_keys) || num_keys < required_sigs) return false;
|
||||
|
||||
return (it + 1 == script.end());
|
||||
}
|
||||
|
||||
|
|
@ -186,12 +218,12 @@ TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned c
|
|||
return TxoutType::PUBKEYHASH;
|
||||
}
|
||||
|
||||
unsigned int required;
|
||||
int required;
|
||||
std::vector<std::vector<unsigned char>> keys;
|
||||
if (MatchMultisig(scriptPubKey, required, keys)) {
|
||||
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
|
||||
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..20
|
||||
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
|
||||
vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
|
||||
vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..20
|
||||
return TxoutType::MULTISIG;
|
||||
}
|
||||
|
||||
|
|
@ -352,10 +384,11 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
|
|||
{
|
||||
CScript script;
|
||||
|
||||
script << CScript::EncodeOP_N(nRequired);
|
||||
script << nRequired;
|
||||
for (const CPubKey& key : keys)
|
||||
script << ToByteVector(key);
|
||||
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
|
||||
script << keys.size() << OP_CHECKMULTISIG;
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue