X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fscript.cpp;h=bbb32f68c7da3a14e21046081f26183227f75774;hb=b2de28c74040595fa3fe5353ea063a8c3874f6b1;hp=6e7bcb5e14c20abe50edca0492755045745f426e;hpb=6cc4a62c0e696dcb9d90ba0504f688e4f644a10f;p=novacoin.git diff --git a/src/script.cpp b/src/script.cpp index 6e7bcb5..bbb32f6 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2011 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" using namespace std; @@ -1132,6 +1132,7 @@ bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* ke if (keystore == NULL || keystore->HaveKey(addressRet)) return true; } + return false; } @@ -1146,16 +1147,40 @@ bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBit } -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType) +bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, + bool fValidatePayToScriptHash, int nHashType) { - vector > stack; + vector > stack, stackCopy; if (!EvalScript(stack, scriptSig, txTo, nIn, nHashType)) return false; + if (fValidatePayToScriptHash) + stackCopy = stack; if (!EvalScript(stack, scriptPubKey, txTo, nIn, nHashType)) return false; if (stack.empty()) return false; - return CastToBool(stack.back()); + + if (CastToBool(stack.back()) == false) + return false; + + // Additional validation for spend-to-script-hash transactions: + if (fValidatePayToScriptHash && scriptPubKey.IsPayToScriptHash()) + { + if (!scriptSig.IsPushOnly()) // scriptSig must be literals-only + return false; // or validation fails + + const valtype& pubKeySerialized = stackCopy.back(); + CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); + popstack(stackCopy); + + if (!EvalScript(stackCopy, pubKey2, txTo, nIn, nHashType)) + return false; + if (stackCopy.empty()) + return false; + return CastToBool(stackCopy.back()); + } + + return true; } @@ -1177,14 +1202,14 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTrans // Test solution if (scriptPrereq.empty()) - if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, 0)) + if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, true, 0)) return false; return true; } -bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType) +bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType) { assert(nIn < txTo.vin.size()); const CTxIn& txin = txTo.vin[nIn]; @@ -1195,8 +1220,65 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig if (txin.prevout.hash != txFrom.GetHash()) return false; - if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType)) + if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, fValidatePayToScriptHash, nHashType)) return false; return true; } + +int CScript::GetSigOpCount(bool fAccurate) const +{ + int n = 0; + const_iterator pc = begin(); + opcodetype lastOpcode = OP_INVALIDOPCODE; + while (pc < end()) + { + opcodetype opcode; + if (!GetOp(pc, opcode)) + break; + if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY) + n++; + else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY) + { + if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16) + n += DecodeOP_N(lastOpcode); + else + n += 20; + } + lastOpcode = opcode; + } + return n; +} + +int CScript::GetSigOpCount(const CScript& scriptSig) const +{ + if (!IsPayToScriptHash()) + return GetSigOpCount(true); + + // This is a pay-to-script-hash scriptPubKey; + // get the last item that the scriptSig + // pushes onto the stack: + const_iterator pc = scriptSig.begin(); + vector data; + while (pc < scriptSig.end()) + { + opcodetype opcode; + if (!scriptSig.GetOp(pc, opcode, data)) + return 0; + if (opcode > OP_16) + return 0; + } + + /// ... and return it's opcount: + CScript subscript(data.begin(), data.end()); + return subscript.GetSigOpCount(true); +} + +bool CScript::IsPayToScriptHash() const +{ + // Extra-fast test for pay-to-script-hash CScripts: + return (this->size() == 23 && + this->at(0) == OP_HASH160 && + this->at(1) == 0x14 && + this->at(22) == OP_EQUAL); +}