aboutsummaryrefslogtreecommitdiff
path: root/src/script/interpreter.cpp
diff options
context:
space:
mode:
authorLuke Dashjr <[email protected]>2016-08-09 05:45:50 +0000
committerLuke Dashjr <[email protected]>2016-08-09 05:45:50 +0000
commitdf634908ba758232413c50e8f1f7a80d546d777b (patch)
tree92cccae378b192f5f70986d2167209cbfd24ae08 /src/script/interpreter.cpp
parentBugfix: Only use git for build info if the repository is actually the right one (diff)
parentqt: periodic translations update (diff)
downloaddiscoin-df634908ba758232413c50e8f1f7a80d546d777b.tar.xz
discoin-df634908ba758232413c50e8f1f7a80d546d777b.zip
Merge tag 'branch-0.13' into bugfix_gitdir
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r--src/script/interpreter.cpp611
1 files changed, 499 insertions, 112 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 3231f2e74..bc027e9f0 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,6 @@
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
-#include "eccryptoverify.h"
#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
@@ -60,7 +59,7 @@ bool CastToBool(const valtype& vch)
static inline void popstack(vector<valtype>& stack)
{
if (stack.empty())
- throw runtime_error("popstack() : stack empty");
+ throw runtime_error("popstack(): stack empty");
stack.pop_back();
}
@@ -93,87 +92,82 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
* in which case a single 0 byte is necessary and even required).
*
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
+ *
+ * This function is consensus-critical since BIP66.
*/
-bool static IsDERSignature(const valtype &vchSig) {
+bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
+ // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
+ // * total-length: 1-byte length descriptor of everything that follows,
+ // excluding the sighash byte.
+ // * R-length: 1-byte length descriptor of the R value that follows.
+ // * R: arbitrary-length big-endian encoded R value. It must use the shortest
+ // possible encoding for a positive integers (which means no null bytes at
+ // the start, except a single one when the next byte has its highest bit set).
+ // * S-length: 1-byte length descriptor of the S value that follows.
+ // * S: arbitrary-length big-endian encoded S value. The same rules apply.
+ // * sighash: 1-byte value indicating what data is hashed (not part of the DER
+ // signature)
- if (vchSig.size() < 9) {
- // Non-canonical signature: too short
- return false;
- }
- if (vchSig.size() > 73) {
- // Non-canonical signature: too long
- return false;
- }
- if (vchSig[0] != 0x30) {
- // Non-canonical signature: wrong type
- return false;
- }
- if (vchSig[1] != vchSig.size()-3) {
- // Non-canonical signature: wrong length marker
- return false;
- }
- unsigned int nLenR = vchSig[3];
- if (5 + nLenR >= vchSig.size()) {
- // Non-canonical signature: S length misplaced
- return false;
- }
- unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) {
- // Non-canonical signature: R+S length mismatch
- return false;
- }
+ // Minimum and maximum size constraints.
+ if (sig.size() < 9) return false;
+ if (sig.size() > 73) return false;
- const unsigned char *R = &vchSig[4];
- if (R[-2] != 0x02) {
- // Non-canonical signature: R value type mismatch
- return false;
- }
- if (nLenR == 0) {
- // Non-canonical signature: R length is zero
- return false;
- }
- if (R[0] & 0x80) {
- // Non-canonical signature: R value negative
- return false;
- }
- if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) {
- // Non-canonical signature: R value excessively padded
- return false;
- }
+ // A signature is of type 0x30 (compound).
+ if (sig[0] != 0x30) return false;
+
+ // Make sure the length covers the entire signature.
+ if (sig[1] != sig.size() - 3) return false;
+
+ // Extract the length of the R element.
+ unsigned int lenR = sig[3];
+
+ // Make sure the length of the S element is still inside the signature.
+ if (5 + lenR >= sig.size()) return false;
+
+ // Extract the length of the S element.
+ unsigned int lenS = sig[5 + lenR];
+
+ // Verify that the length of the signature matches the sum of the length
+ // of the elements.
+ if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
+
+ // Check whether the R element is an integer.
+ if (sig[2] != 0x02) return false;
+
+ // Zero-length integers are not allowed for R.
+ if (lenR == 0) return false;
+
+ // Negative numbers are not allowed for R.
+ if (sig[4] & 0x80) return false;
+
+ // Null bytes at the start of R are not allowed, unless R would
+ // otherwise be interpreted as a negative number.
+ if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
+
+ // Check whether the S element is an integer.
+ if (sig[lenR + 4] != 0x02) return false;
+
+ // Zero-length integers are not allowed for S.
+ if (lenS == 0) return false;
+
+ // Negative numbers are not allowed for S.
+ if (sig[lenR + 6] & 0x80) return false;
+
+ // Null bytes at the start of S are not allowed, unless S would otherwise be
+ // interpreted as a negative number.
+ if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;
- const unsigned char *S = &vchSig[6+nLenR];
- if (S[-2] != 0x02) {
- // Non-canonical signature: S value type mismatch
- return false;
- }
- if (nLenS == 0) {
- // Non-canonical signature: S length is zero
- return false;
- }
- if (S[0] & 0x80) {
- // Non-canonical signature: S value negative
- return false;
- }
- if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) {
- // Non-canonical signature: S value excessively padded
- return false;
- }
return true;
}
bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
- if (!IsDERSignature(vchSig)) {
+ if (!IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
}
- unsigned int nLenR = vchSig[3];
- unsigned int nLenS = vchSig[5+nLenR];
- const unsigned char *S = &vchSig[6+nLenR];
- // If the S value is above the order of the curve divided by two, its
- // complement modulo the order could have been used instead, which is
- // one byte shorter when encoded correctly.
- if (!eccrypto::CheckSignatureElement(S, nLenS, true))
+ std::vector<unsigned char> vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1);
+ if (!CPubKey::CheckLowS(vchSigCopy)) {
return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
-
+ }
return true;
}
@@ -188,8 +182,13 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
return true;
}
-bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
- if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
+bool CheckSignatureEncoding(const vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror) {
+ // Empty signature. Not strictly DER encoded, but allowed to provide a
+ // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
+ if (vchSig.size() == 0) {
+ return true;
+ }
+ if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
} else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
// serror is set
@@ -230,7 +229,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
@@ -248,7 +247,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
vector<bool> vfExec;
vector<valtype> altstack;
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
- if (script.size() > 10000)
+ if (script.size() > MAX_SCRIPT_SIZE)
return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
int nOpCount = 0;
bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;
@@ -268,7 +267,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
- if (opcode > OP_16 && ++nOpCount > 201)
+ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
@@ -330,9 +329,88 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Control
//
case OP_NOP:
- break;
+ break;
+
+ case OP_CHECKLOCKTIMEVERIFY:
+ {
+ if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
+ // not enabled; treat as a NOP2
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
+
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // Note that elsewhere numeric opcodes are limited to
+ // operands in the range -2**31+1 to 2**31-1, however it is
+ // legal for opcodes to produce results exceeding that
+ // range. This limitation is implemented by CScriptNum's
+ // default 4-byte limit.
+ //
+ // If we kept to that limit we'd have a year 2038 problem,
+ // even though the nLockTime field in transactions
+ // themselves is uint32 which only becomes meaningless
+ // after the year 2106.
+ //
+ // Thus as a special case we tell CScriptNum to accept up
+ // to 5-byte bignums, which are good until 2**39-1, well
+ // beyond the 2**32-1 limit of the nLockTime field itself.
+ const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKLOCKTIMEVERIFY.
+ if (nLockTime < 0)
+ return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // Actually compare the specified lock time with the transaction.
+ if (!checker.CheckLockTime(nLockTime))
+ return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
+ break;
+ }
+
+ case OP_CHECKSEQUENCEVERIFY:
+ {
+ if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
+ // not enabled; treat as a NOP3
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
+
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // nSequence, like nLockTime, is a 32-bit unsigned integer
+ // field. See the comment in CHECKLOCKTIMEVERIFY regarding
+ // 5-byte numeric operands.
+ const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKSEQUENCEVERIFY.
+ if (nSequence < 0)
+ return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // To provide for future soft-fork extensibility, if the
+ // operand has the disabled lock-time flag set,
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
+ if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
+ break;
+
+ // Compare the specified sequence number with the input.
+ if (!checker.CheckSequence(nSequence))
+ return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
+ break;
+ }
- case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
+ case OP_NOP1: case OP_NOP4: case OP_NOP5:
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
{
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
@@ -791,13 +869,15 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
CScript scriptCode(pbegincodehash, pend);
// Drop the signature, since there's no way for a signature to sign itself
- scriptCode.FindAndDelete(CScript(vchSig));
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
//serror is set
return false;
}
- bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
+ bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
popstack(stack);
popstack(stack);
@@ -822,10 +902,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nKeysCount < 0 || nKeysCount > 20)
+ if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
- if (nOpCount > 201)
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
@@ -847,7 +927,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
for (int k = 0; k < nSigsCount; k++)
{
valtype& vchSig = stacktop(-isig-k);
- scriptCode.FindAndDelete(CScript(vchSig));
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
}
bool fSuccess = true;
@@ -865,7 +947,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
// Check signature
- bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode);
+ bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
if (fOk) {
isig++;
@@ -937,12 +1019,12 @@ namespace {
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction &txTo; //! reference to the spending transaction (the one being serialized)
- const CScript &scriptCode; //! output script being consumed
- const unsigned int nIn; //! input index of txTo being signed
- const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set
- const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; //! whether the hashtype is SIGHASH_NONE
+ const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const CScript& scriptCode; //!< output script being consumed
+ const unsigned int nIn; //!< input index of txTo being signed
+ const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
@@ -985,7 +1067,7 @@ public:
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
- ::Serialize(s, CScript(), nType, nVersion);
+ ::Serialize(s, CScriptBase(), nType, nVersion);
else
SerializeScriptCode(s, nType, nVersion);
// Serialize the nSequence
@@ -1028,18 +1110,75 @@ public:
} // anon namespace
-uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion)
{
+ if (sigversion == SIGVERSION_WITNESS_V0) {
+ uint256 hashPrevouts;
+ uint256 hashSequence;
+ uint256 hashOutputs;
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY)) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].prevout;
+ }
+ hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ }
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].nSequence;
+ }
+ hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ }
+
+ if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vout.size(); n++) {
+ ss << txTo.vout[n];
+ }
+ hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTo.vout[nIn];
+ hashOutputs = ss.GetHash();
+ }
+
+ CHashWriter ss(SER_GETHASH, 0);
+ // Version
+ ss << txTo.nVersion;
+ // Input prevouts/nSequence (none/all, depending on flags)
+ ss << hashPrevouts;
+ ss << hashSequence;
+ // The input being signed (replacing the scriptSig with scriptCode + amount)
+ // The prevout may already be contained in hashPrevout, and the nSequence
+ // may already be contain in hashSequence.
+ ss << txTo.vin[nIn].prevout;
+ ss << static_cast<const CScriptBase&>(scriptCode);
+ ss << amount;
+ ss << txTo.vin[nIn].nSequence;
+ // Outputs (none/one/all, depending on flags)
+ ss << hashOutputs;
+ // Locktime
+ ss << txTo.nLockTime;
+ // Sighash type
+ ss << nHashType;
+
+ return ss.GetHash();
+ }
+
+ static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size()) {
// nIn out of range
- return 1;
+ return one;
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
// nOut out of range
- return 1;
+ return one;
}
}
@@ -1052,12 +1191,12 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
-bool SignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
return pubkey.Verify(sighash, vchSig);
}
-bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
+bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@@ -1070,7 +1209,7 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
int nHashType = vchSig.back();
vchSig.pop_back();
- uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType);
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
if (!VerifySignature(vchSig, pubkey, sighash))
return false;
@@ -1078,8 +1217,149 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
+{
+ // There are two kinds of nLockTime: lock-by-blockheight
+ // and lock-by-blocktime, distinguished by whether
+ // nLockTime < LOCKTIME_THRESHOLD.
+ //
+ // We want to compare apples to apples, so fail the script
+ // unless the type of nLockTime being tested is the same as
+ // the nLockTime in the transaction.
+ if (!(
+ (txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
+ (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
+ ))
+ return false;
+
+ // Now that we know we're comparing apples-to-apples, the
+ // comparison is a simple numeric one.
+ if (nLockTime > (int64_t)txTo->nLockTime)
+ return false;
+
+ // Finally the nLockTime feature can be disabled and thus
+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been
+ // finalized by setting nSequence to maxint. The
+ // transaction would be allowed into the blockchain, making
+ // the opcode ineffective.
+ //
+ // Testing if this vin is not final is sufficient to
+ // prevent this condition. Alternatively we could test all
+ // inputs, but testing just this input minimizes the data
+ // required to prove correct CHECKLOCKTIMEVERIFY execution.
+ if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence)
+ return false;
+
+ return true;
+}
+
+bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
+{
+ // Relative lock times are supported by comparing the passed
+ // in operand to the sequence number of the input.
+ const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
+
+ // Fail if the transaction's version number is not set high
+ // enough to trigger BIP 68 rules.
+ if (static_cast<uint32_t>(txTo->nVersion) < 2)
+ return false;
+
+ // Sequence numbers with their most significant bit set are not
+ // consensus constrained. Testing that the transaction's sequence
+ // number do not have this bit set prevents using this property
+ // to get around a CHECKSEQUENCEVERIFY check.
+ if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
+ return false;
+
+ // Mask off any bits that do not have consensus-enforced meaning
+ // before doing the integer comparisons
+ const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
+ const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
+ const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
+
+ // There are two kinds of nSequence: lock-by-blockheight
+ // and lock-by-blocktime, distinguished by whether
+ // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
+ //
+ // We want to compare apples to apples, so fail the script
+ // unless the type of nSequenceMasked being tested is the same as
+ // the nSequenceMasked in the transaction.
+ if (!(
+ (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
+ (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
+ )) {
+ return false;
+ }
+
+ // Now that we know we're comparing apples-to-apples, the
+ // comparison is a simple numeric one.
+ if (nSequenceMasked > txToSequenceMasked)
+ return false;
+
+ return true;
+}
+
+static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+{
+ vector<vector<unsigned char> > stack;
+ CScript scriptPubKey;
+
+ if (witversion == 0) {
+ if (program.size() == 32) {
+ // Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness
+ if (witness.stack.size() == 0) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
+ }
+ scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
+ stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 1);
+ uint256 hashScriptPubKey;
+ CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
+ if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+ }
+ } else if (program.size() == 20) {
+ // Special case for pay-to-pubkeyhash; signature + pubkey in witness
+ if (witness.stack.size() != 2) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
+ }
+ scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
+ stack = witness.stack;
+ } else {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
+ }
+ } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ } else {
+ // Higher version witness scripts return true for future softfork compatibility
+ return set_success(serror);
+ }
+
+ // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
+ for (unsigned int i = 0; i < stack.size(); i++) {
+ if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE)
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+ }
+
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) {
+ return false;
+ }
+
+ // Scripts inside witness implicitly require cleanstack behaviour
+ if (stack.size() != 1)
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stack.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ return true;
+}
+
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
+ static const CScriptWitness emptyWitness;
+ if (witness == NULL) {
+ witness = &emptyWitness;
+ }
+ bool hadWitness = false;
+
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
@@ -1087,20 +1367,38 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
}
vector<vector<unsigned char> > stack, stackCopy;
- if (!EvalScript(stack, scriptSig, flags, checker, serror))
+ if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
if (stack.empty())
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
-
if (CastToBool(stack.back()) == false)
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ // Bare witness programs
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig.size() != 0) {
+ // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
+
// Additional validation for spend-to-script-hash transactions:
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
{
@@ -1108,25 +1406,114 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
if (!scriptSig.IsPushOnly())
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
- // stackCopy cannot be empty here, because if it was the
+ // Restore stack.
+ swap(stack, stackCopy);
+
+ // stack cannot be empty here, because if it was the
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
// an empty stack and the EvalScript above would return false.
- assert(!stackCopy.empty());
+ assert(!stack.empty());
- const valtype& pubKeySerialized = stackCopy.back();
+ const valtype& pubKeySerialized = stack.back();
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
- popstack(stackCopy);
+ popstack(stack);
- if (!EvalScript(stackCopy, pubKey2, flags, checker, serror))
+ if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
- if (stackCopy.empty())
+ if (stack.empty())
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
- if (!CastToBool(stackCopy.back()))
+ if (!CastToBool(stack.back()))
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
- else
- return set_success(serror);
+
+ // P2SH witness program
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig != CScript() << std::vector<unsigned char>(pubKey2.begin(), pubKey2.end())) {
+ // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we
+ // reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
+ }
+
+ // The CLEANSTACK check is only performed after potential P2SH evaluation,
+ // as the non-P2SH evaluation of a P2SH script will obviously not result in
+ // a clean stack (the P2SH inputs remain). The same holds for witness evaluation.
+ if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
+ // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
+ // would be possible, which is not a softfork (and P2SH should be one).
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ assert((flags & SCRIPT_VERIFY_WITNESS) != 0);
+ if (stack.size() != 1) {
+ return set_error(serror, SCRIPT_ERR_CLEANSTACK);
+ }
+ }
+
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ // We can't check for correct unexpected witness data if P2SH was off, so require
+ // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be
+ // possible, which is not a softfork.
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ if (!hadWitness && !witness->IsNull()) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED);
+ }
}
return set_success(serror);
}
+
+size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& witprogram, const CScriptWitness& witness, int flags)
+{
+ if (witversion == 0) {
+ if (witprogram.size() == 20)
+ return 1;
+
+ if (witprogram.size() == 32 && witness.stack.size() > 0) {
+ CScript subscript(witness.stack.back().begin(), witness.stack.back().end());
+ return subscript.GetSigOpCount(true);
+ }
+ }
+
+ // Future flags may be implemented here.
+ return 0;
+}
+
+size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags)
+{
+ static const CScriptWitness witnessEmpty;
+
+ if ((flags & SCRIPT_VERIFY_WITNESS) == 0) {
+ return 0;
+ }
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+
+ int witnessversion;
+ std::vector<unsigned char> witnessprogram;
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+
+ if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) {
+ CScript::const_iterator pc = scriptSig.begin();
+ vector<unsigned char> data;
+ while (pc < scriptSig.end()) {
+ opcodetype opcode;
+ scriptSig.GetOp(pc, opcode, data);
+ }
+ CScript subscript(data.begin(), data.end());
+ if (subscript.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+ }
+
+ return 0;
+}