diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -961,17 +961,16 @@ case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { - // ([sig ...] num_of_signatures [pubkey ...] + // ([dummy] [sig ...] num_of_signatures [pubkey ...] // num_of_pubkeys -- bool) - - int i = 1; - if ((int)stack.size() < i) { + const int idxKeyCount = 1; + if (stack.size() < idxKeyCount) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } - - int nKeysCount = - CScriptNum(stacktop(-i), fRequireMinimal).getint(); + const int nKeysCount = + CScriptNum(stacktop(-idxKeyCount), fRequireMinimal) + .getint(); if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG) { return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT); @@ -980,26 +979,32 @@ if (nOpCount > MAX_OPS_PER_SCRIPT) { return set_error(serror, SCRIPT_ERR_OP_COUNT); } - int ikey = ++i; - // ikey2 is the position of last non-signature item in - // the stack. Top stack item = 1. With - // SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if - // operation fails. - int ikey2 = nKeysCount + 2; - i += nKeysCount; - if ((int)stack.size() < i) { + + // position of the top pubkey on stack + const int idxTopKey = idxKeyCount + 1; + + // idxSigCount the position of nSigsCount, the stack + // element that sits between the signatures list and + // pubkeys list. + const int idxSigCount = idxTopKey + nKeysCount; + if (stack.size() < size_t(idxSigCount)) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } - - int nSigsCount = - CScriptNum(stacktop(-i), fRequireMinimal).getint(); + const int nSigsCount = + CScriptNum(stacktop(-idxSigCount), fRequireMinimal) + .getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) { return set_error(serror, SCRIPT_ERR_SIG_COUNT); } - int isig = ++i; - i += nSigsCount; - if ((int)stack.size() < i) { + + // position of the top signature on stack + const int idxTopSig = idxSigCount + 1; + + // position of the dummy element on stack + const int idxDummy = idxTopSig + nSigsCount; + + if (stack.size() < size_t(idxDummy)) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } @@ -1010,12 +1015,16 @@ // Remove signature for pre-fork scripts for (int k = 0; k < nSigsCount; k++) { - valtype &vchSig = stacktop(-isig - k); + valtype &vchSig = stacktop(-idxTopSig - k); CleanupScriptCode(scriptCode, vchSig, flags); } bool fSuccess = true; - while (fSuccess && nSigsCount > 0) { + int ikey = idxTopKey; + int isig = idxTopSig; + int nSigsRemaining = nSigsCount; + int nKeysRemaining = nKeysCount; + while (fSuccess && nSigsRemaining > 0) { valtype &vchSig = stacktop(-isig); valtype &vchPubKey = stacktop(-ikey); @@ -1037,20 +1046,22 @@ if (fOk) { isig++; - nSigsCount--; + nSigsRemaining--; } ikey++; - nKeysCount--; + nKeysRemaining--; // If there are more signatures left than keys left, // then too many signatures have failed. Exit early, // without checking any further signatures. - if (nSigsCount > nKeysCount) { + if (nSigsRemaining > nKeysRemaining) { fSuccess = false; } } // Clean up stack of actual arguments + int i = idxDummy; + int ikey2 = idxSigCount; while (i-- > 1) { // If the operation failed, we require that all // signatures must be empty vector