Changeset View
Changeset View
Standalone View
Standalone View
src/script/interpreter.cpp
Show First 20 Lines • Show All 964 Lines • ▼ Show 20 Lines | try { | ||||
} | } | ||||
} break; | } break; | ||||
case OP_CHECKMULTISIG: | case OP_CHECKMULTISIG: | ||||
case OP_CHECKMULTISIGVERIFY: { | case OP_CHECKMULTISIGVERIFY: { | ||||
// ([sig ...] num_of_signatures [pubkey ...] | // ([sig ...] num_of_signatures [pubkey ...] | ||||
// num_of_pubkeys -- bool) | // num_of_pubkeys -- bool) | ||||
uint32_t msigflags = flags & ~SCRIPT_ENABLE_SCHNORR; | |||||
int i = 1; | int i = 1; | ||||
if ((int)stack.size() < i) { | if ((int)stack.size() < i) { | ||||
return set_error( | return set_error( | ||||
serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | ||||
} | } | ||||
int nKeysCount = | int nKeysCount = | ||||
CScriptNum(stacktop(-i), fRequireMinimal).getint(); | CScriptNum(stacktop(-i), fRequireMinimal).getint(); | ||||
Show All 31 Lines | try { | ||||
// Subset of script starting at the most recent | // Subset of script starting at the most recent | ||||
// codeseparator | // codeseparator | ||||
CScript scriptCode(pbegincodehash, pend); | CScript scriptCode(pbegincodehash, pend); | ||||
// Remove signature for pre-fork scripts | // Remove signature for pre-fork scripts | ||||
for (int k = 0; k < nSigsCount; k++) { | for (int k = 0; k < nSigsCount; k++) { | ||||
valtype &vchSig = stacktop(-isig - k); | valtype &vchSig = stacktop(-isig - k); | ||||
CleanupScriptCode(scriptCode, vchSig, flags); | CleanupScriptCode(scriptCode, vchSig, msigflags); | ||||
} | } | ||||
bool fSuccess = true; | bool fSuccess = true; | ||||
while (fSuccess && nSigsCount > 0) { | while (fSuccess && nSigsCount > 0) { | ||||
valtype &vchSig = stacktop(-isig); | valtype &vchSig = stacktop(-isig); | ||||
valtype &vchPubKey = stacktop(-ikey); | valtype &vchPubKey = stacktop(-ikey); | ||||
// Note how this makes the exact order of | // Note how this makes the exact order of | ||||
// pubkey/signature evaluation distinguishable by | // pubkey/signature evaluation distinguishable by | ||||
// CHECKMULTISIG NOT if the STRICTENC flag is set. | // CHECKMULTISIG NOT if the STRICTENC flag is set. | ||||
// See the script_(in)valid tests for details. | // See the script_(in)valid tests for details. | ||||
if (!CheckTransactionSignatureEncoding( | if (!CheckTransactionSignatureEncoding( | ||||
vchSig, flags, serror) || | vchSig, msigflags, serror) || | ||||
!CheckPubKeyEncoding(vchPubKey, flags, | !CheckPubKeyEncoding(vchPubKey, msigflags, | ||||
serror)) { | serror)) { | ||||
// serror is set | // serror is set | ||||
return false; | return false; | ||||
} | } | ||||
// Check signature | // Check signature | ||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, | bool fOk = checker.CheckSig(vchSig, vchPubKey, | ||||
scriptCode, flags); | scriptCode, msigflags); | ||||
if (fOk) { | if (fOk) { | ||||
isig++; | isig++; | ||||
nSigsCount--; | nSigsCount--; | ||||
} | } | ||||
ikey++; | ikey++; | ||||
nKeysCount--; | nKeysCount--; | ||||
// If there are more signatures left than keys left, | // If there are more signatures left than keys left, | ||||
// then too many signatures have failed. Exit early, | // then too many signatures have failed. Exit early, | ||||
// without checking any further signatures. | // without checking any further signatures. | ||||
if (nSigsCount > nKeysCount) { | if (nSigsCount > nKeysCount) { | ||||
fSuccess = false; | fSuccess = false; | ||||
} | } | ||||
} | } | ||||
// Clean up stack of actual arguments | // Clean up stack of actual arguments | ||||
while (i-- > 1) { | while (i-- > 1) { | ||||
// If the operation failed, we require that all | // If the operation failed, we require that all | ||||
// signatures must be empty vector | // signatures must be empty vector | ||||
if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && | if (!fSuccess && | ||||
(msigflags & SCRIPT_VERIFY_NULLFAIL) && | |||||
!ikey2 && stacktop(-1).size()) { | !ikey2 && stacktop(-1).size()) { | ||||
return set_error(serror, | return set_error(serror, | ||||
SCRIPT_ERR_SIG_NULLFAIL); | SCRIPT_ERR_SIG_NULLFAIL); | ||||
} | } | ||||
if (ikey2 > 0) { | if (ikey2 > 0) { | ||||
ikey2--; | ikey2--; | ||||
} | } | ||||
popstack(stack); | popstack(stack); | ||||
} | } | ||||
// A bug causes CHECKMULTISIG to consume one extra | // A bug causes CHECKMULTISIG to consume one extra | ||||
// argument whose contents were not checked in any way. | // argument whose contents were not checked in any way. | ||||
// | // | ||||
// Unfortunately this is a potential source of | // Unfortunately this is a potential source of | ||||
// mutability, so optionally verify it is exactly equal | // mutability, so optionally verify it is exactly equal | ||||
// to zero prior to removing it from the stack. | // to zero prior to removing it from the stack. | ||||
if (stack.size() < 1) { | if (stack.size() < 1) { | ||||
return set_error( | return set_error( | ||||
serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | ||||
} | } | ||||
if ((flags & SCRIPT_VERIFY_NULLDUMMY) && | if ((msigflags & SCRIPT_VERIFY_NULLDUMMY) && | ||||
stacktop(-1).size()) { | stacktop(-1).size()) { | ||||
return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY); | return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY); | ||||
} | } | ||||
popstack(stack); | popstack(stack); | ||||
stack.push_back(fSuccess ? vchTrue : vchFalse); | stack.push_back(fSuccess ? vchTrue : vchFalse); | ||||
if (opcode == OP_CHECKMULTISIGVERIFY) { | if (opcode == OP_CHECKMULTISIGVERIFY) { | ||||
▲ Show 20 Lines • Show All 369 Lines • ▼ Show 20 Lines | uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, | ||||
ss << txTmp << sigHashType; | ss << txTmp << sigHashType; | ||||
return ss.GetHash(); | return ss.GetHash(); | ||||
} | } | ||||
bool BaseSignatureChecker::VerifySignature(const std::vector<uint8_t> &vchSig, | bool BaseSignatureChecker::VerifySignature(const std::vector<uint8_t> &vchSig, | ||||
const CPubKey &pubkey, | const CPubKey &pubkey, | ||||
const uint256 &sighash, | const uint256 &sighash, | ||||
uint32_t flags) const { | uint32_t flags) const { | ||||
if ((flags & SCRIPT_ENABLE_SCHNORR) && (vchSig.size() == 64)) { | |||||
return pubkey.VerifySchnorr(sighash, vchSig); | |||||
} else { | |||||
return pubkey.VerifyECDSA(sighash, vchSig); | return pubkey.VerifyECDSA(sighash, vchSig); | ||||
} | } | ||||
} | |||||
bool TransactionSignatureChecker::CheckSig( | bool TransactionSignatureChecker::CheckSig( | ||||
const std::vector<uint8_t> &vchSigIn, const std::vector<uint8_t> &vchPubKey, | const std::vector<uint8_t> &vchSigIn, const std::vector<uint8_t> &vchPubKey, | ||||
const CScript &scriptCode, uint32_t flags) const { | const CScript &scriptCode, uint32_t flags) const { | ||||
CPubKey pubkey(vchPubKey); | CPubKey pubkey(vchPubKey); | ||||
if (!pubkey.IsValid()) { | if (!pubkey.IsValid()) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 187 Lines • Show Last 20 Lines |