Changeset View
Changeset View
Standalone View
Standalone View
src/script/interpreter.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Copyright (c) 2017-2018 The Bitcoin developers | // Copyright (c) 2017-2018 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <script/interpreter.h> | #include <script/interpreter.h> | ||||
#include <crypto/ripemd160.h> | #include <crypto/ripemd160.h> | ||||
#include <crypto/sha1.h> | #include <crypto/sha1.h> | ||||
#include <crypto/sha256.h> | #include <crypto/sha256.h> | ||||
#include <primitives/transaction.h> | #include <primitives/transaction.h> | ||||
#include <pubkey.h> | #include <pubkey.h> | ||||
#include <reverse_iterator.h> | |||||
#include <script/script.h> | #include <script/script.h> | ||||
#include <script/script_flags.h> | #include <script/script_flags.h> | ||||
#include <script/sigencoding.h> | #include <script/sigencoding.h> | ||||
#include <uint256.h> | #include <uint256.h> | ||||
bool CastToBool(const valtype &vch) { | bool CastToBool(const valtype &vch) { | ||||
for (size_t i = 0; i < vch.size(); i++) { | for (size_t i = 0; i < vch.size(); i++) { | ||||
if (vch[i] != 0) { | if (vch[i] != 0) { | ||||
▲ Show 20 Lines • Show All 979 Lines • ▼ Show 20 Lines | try { | ||||
// stack depth of the dummy element | // stack depth of the dummy element | ||||
const size_t idxDummy = idxTopSig + nSigsCount; | const size_t idxDummy = idxTopSig + nSigsCount; | ||||
if (stack.size() < idxDummy) { | if (stack.size() < idxDummy) { | ||||
return set_error( | return set_error( | ||||
serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | ||||
} | } | ||||
// Subset of script starting at the most recent | |||||
// codeseparator | |||||
CScript scriptCode(pbegincodehash, pend); | |||||
bool fSuccess = true; | |||||
int nSigsRemaining = nSigsCount; | |||||
int nKeysRemaining = nKeysCount; | |||||
if ((flags & SCRIPT_ENABLE_SCHNORR_MULTISIG) && | |||||
(stacktop(-idxDummy).size() != 0)) { | |||||
// NEW MULTISIG (SCHNORR / NULL) | |||||
// Dummy element is to be interpreted as a bitfield | |||||
// that represent which pubkeys should be checked. | |||||
valtype &vchDummy = stacktop(-idxDummy); | |||||
// Its byte-length must be the minimum to hold | |||||
// nPubKeys bits. | |||||
if (vchDummy.size() != | |||||
size_t((nKeysCount + 7) / 8)) { | |||||
return set_error(serror, | |||||
SCRIPT_ERR_INVALID_CHECKBITS); | |||||
} | |||||
static_assert(MAX_PUBKEYS_PER_MULTISIG <= 32); | |||||
uint32_t checkBits = 0; | |||||
// Decode the bitfield (little-endian) | |||||
for (uint8_t b : reverse_iterate(vchDummy)) { | |||||
checkBits = (checkBits << 8) | b; | |||||
} | |||||
for (; nSigsRemaining > 0 && nKeysRemaining > 0; | |||||
checkBits >>= 1, nKeysRemaining--) { | |||||
if ((checkBits & 1) == 0) { | |||||
continue; | |||||
} | |||||
valtype &vchSig = stacktop( | |||||
-idxTopSig - (nSigsCount - nSigsRemaining)); | |||||
valtype &vchPubKey = stacktop( | |||||
-idxTopKey - (nKeysCount - nKeysRemaining)); | |||||
if (!CheckTransactionSchnorrSignatureEncoding( | |||||
vchSig, flags, serror) || | |||||
!CheckPubKeyEncoding(vchPubKey, flags, | |||||
serror)) { | |||||
// serror is set | |||||
return false; | |||||
} | |||||
if (!checker.CheckSig(vchSig, vchPubKey, | |||||
scriptCode, flags)) { | |||||
// It is forbidden to request an invalid | |||||
// signature. | |||||
return set_error( | |||||
serror, | |||||
vchSig.size() | |||||
? SCRIPT_ERR_SIG_NULLFAIL | |||||
: SCRIPT_ERR_INVALID_CHECKBITS); | |||||
} | |||||
// A successful checksig is the only way to | |||||
// decrement nSigsRemaining. | |||||
nSigsRemaining--; | |||||
} | |||||
if (nSigsRemaining > 0) { | |||||
// Ended before checking all signatures, because | |||||
// too few bits were set. | |||||
return set_error(serror, | |||||
SCRIPT_ERR_INVALID_CHECKBITS); | |||||
} | |||||
if (checkBits != 0) { | |||||
// Ended before consuming all bits, because too | |||||
// many bits were set or a too-high bit was set. | |||||
return set_error(serror, | |||||
SCRIPT_ERR_INVALID_CHECKBITS); | |||||
} | |||||
} else { | |||||
// LEGACY MULTISIG (ECDSA / NULL) | |||||
// 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 | ||||
// to zero. | // equal to zero. | ||||
if ((flags & SCRIPT_VERIFY_NULLDUMMY) && | if ((flags & SCRIPT_VERIFY_NULLDUMMY) && | ||||
stacktop(-idxDummy).size()) { | stacktop(-idxDummy).size()) { | ||||
return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY); | return set_error(serror, | ||||
SCRIPT_ERR_SIG_NULLDUMMY); | |||||
} | } | ||||
// Subset of script starting at the most recent | |||||
// codeseparator | |||||
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(-idxTopSig - k); | valtype &vchSig = stacktop(-idxTopSig - k); | ||||
CleanupScriptCode(scriptCode, vchSig, flags); | CleanupScriptCode(scriptCode, vchSig, flags); | ||||
} | } | ||||
bool fSuccess = true; | |||||
int nSigsRemaining = nSigsCount; | |||||
int nKeysRemaining = nKeysCount; | |||||
while (fSuccess && nSigsRemaining > 0) { | while (fSuccess && nSigsRemaining > 0) { | ||||
valtype &vchSig = stacktop( | valtype &vchSig = stacktop( | ||||
-idxTopSig - (nSigsCount - nSigsRemaining)); | -idxTopSig - (nSigsCount - nSigsRemaining)); | ||||
valtype &vchPubKey = stacktop( | valtype &vchPubKey = stacktop( | ||||
-idxTopKey - (nKeysCount - nKeysRemaining)); | -idxTopKey - (nKeysCount - nKeysRemaining)); | ||||
// 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 | ||||
// CHECKMULTISIG NOT if the STRICTENC flag is set. | // by CHECKMULTISIG NOT if the STRICTENC flag is | ||||
// See the script_(in)valid tests for details. | // set. See the script_(in)valid tests for | ||||
// details. | |||||
if (!CheckTransactionECDSASignatureEncoding( | if (!CheckTransactionECDSASignatureEncoding( | ||||
vchSig, flags, serror) || | vchSig, flags, serror) || | ||||
!CheckPubKeyEncoding(vchPubKey, flags, | !CheckPubKeyEncoding(vchPubKey, flags, | ||||
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, flags); | ||||
if (fOk) { | if (fOk) { | ||||
nSigsRemaining--; | nSigsRemaining--; | ||||
} | } | ||||
nKeysRemaining--; | nKeysRemaining--; | ||||
// If there are more signatures left than keys left, | // If there are more signatures left than keys | ||||
// then too many signatures have failed. Exit early, | // left, then too many signatures have failed. | ||||
// without checking any further signatures. | // Exit early, without checking any further | ||||
// signatures. | |||||
if (nSigsRemaining > nKeysRemaining) { | if (nSigsRemaining > nKeysRemaining) { | ||||
fSuccess = false; | fSuccess = false; | ||||
} | } | ||||
} | } | ||||
} | |||||
// 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 && (flags & SCRIPT_VERIFY_NULLFAIL)) { | ||||
for (int i = 0; i < nSigsCount; i++) { | for (int i = 0; i < nSigsCount; i++) { | ||||
if (stacktop(-idxTopSig - i).size()) { | if (stacktop(-idxTopSig - i).size()) { | ||||
return set_error(serror, | return set_error(serror, | ||||
SCRIPT_ERR_SIG_NULLFAIL); | SCRIPT_ERR_SIG_NULLFAIL); | ||||
▲ Show 20 Lines • Show All 596 Lines • Show Last 20 Lines |