diff options
Diffstat (limited to 'src/script.cpp')
| -rw-r--r-- | src/script.cpp | 203 |
1 files changed, 15 insertions, 188 deletions
diff --git a/src/script.cpp b/src/script.cpp index f65508aac..90066efd3 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -16,7 +16,7 @@ using namespace boost; #include "sync.h" #include "util.h" -bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags); @@ -54,32 +54,6 @@ bool CastToBool(const valtype& vch) return false; } -// -// WARNING: This does not work as expected for signed integers; the sign-bit -// is left in place as the integer is zero-extended. The correct behavior -// would be to move the most significant bit of the last byte during the -// resize process. MakeSameSize() is currently only used by the disabled -// opcodes OP_AND, OP_OR, and OP_XOR. -// -void MakeSameSize(valtype& vch1, valtype& vch2) -{ - // Lengthen the shorter one - if (vch1.size() < vch2.size()) - // PATCH: - // +unsigned char msb = vch1[vch1.size()-1]; - // +vch1[vch1.size()-1] &= 0x7f; - // vch1.resize(vch2.size(), 0); - // +vch1[vch1.size()-1] = msb; - vch1.resize(vch2.size(), 0); - if (vch2.size() < vch1.size()) - // PATCH: - // +unsigned char msb = vch2[vch2.size()-1]; - // +vch2[vch2.size()-1] &= 0x7f; - // vch2.resize(vch1.size(), 0); - // +vch2[vch2.size()-1] = msb; - vch2.resize(vch1.size(), 0); -} - // @@ -278,7 +252,8 @@ bool IsCanonicalSignature(const valtype &vchSig) { return error("Non-canonical signature: too short"); if (vchSig.size() > 73) return error("Non-canonical signature: too long"); - if (vchSig[vchSig.size() - 1] & 0x7C) + unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); + if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) return error("Non-canonical signature: unknown hashtype byte"); if (vchSig[0] != 0x30) return error("Non-canonical signature: wrong type"); @@ -340,7 +315,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // if (!script.GetOp(pc, opcode, vchPushValue)) return false; - if (vchPushValue.size() > 520) + if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) return false; if (opcode > OP_16 && ++nOpCount > 201) return false; @@ -360,7 +335,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT) - return false; + return false; // Disabled opcodes. if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) stack.push_back(vchPushValue); @@ -658,64 +633,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co break; - // - // Splice ops - // - case OP_CAT: - { - // (x1 x2 -- out) - if (stack.size() < 2) - return false; - valtype& vch1 = stacktop(-2); - valtype& vch2 = stacktop(-1); - vch1.insert(vch1.end(), vch2.begin(), vch2.end()); - popstack(stack); - if (stacktop(-1).size() > 520) - return false; - } - break; - - case OP_SUBSTR: - { - // (in begin size -- out) - if (stack.size() < 3) - return false; - valtype& vch = stacktop(-3); - int nBegin = CastToBigNum(stacktop(-2)).getint(); - int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint(); - if (nBegin < 0 || nEnd < nBegin) - return false; - if (nBegin > (int)vch.size()) - nBegin = vch.size(); - if (nEnd > (int)vch.size()) - nEnd = vch.size(); - vch.erase(vch.begin() + nEnd, vch.end()); - vch.erase(vch.begin(), vch.begin() + nBegin); - popstack(stack); - popstack(stack); - } - break; - - case OP_LEFT: - case OP_RIGHT: - { - // (in size -- out) - if (stack.size() < 2) - return false; - valtype& vch = stacktop(-2); - int nSize = CastToBigNum(stacktop(-1)).getint(); - if (nSize < 0) - return false; - if (nSize > (int)vch.size()) - nSize = vch.size(); - if (opcode == OP_LEFT) - vch.erase(vch.begin() + nSize, vch.end()); - else - vch.erase(vch.begin(), vch.end() - nSize); - popstack(stack); - } - break; - case OP_SIZE: { // (in -- in size) @@ -730,51 +647,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // // Bitwise logic // - case OP_INVERT: - { - // (in - out) - if (stack.size() < 1) - return false; - valtype& vch = stacktop(-1); - for (unsigned int i = 0; i < vch.size(); i++) - vch[i] = ~vch[i]; - } - break; - - // - // WARNING: These disabled opcodes exhibit unexpected behavior - // when used on signed integers due to a bug in MakeSameSize() - // [see definition of MakeSameSize() above]. - // - case OP_AND: - case OP_OR: - case OP_XOR: - { - // (x1 x2 - out) - if (stack.size() < 2) - return false; - valtype& vch1 = stacktop(-2); - valtype& vch2 = stacktop(-1); - MakeSameSize(vch1, vch2); // <-- NOT SAFE FOR SIGNED VALUES - if (opcode == OP_AND) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] &= vch2[i]; - } - else if (opcode == OP_OR) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] |= vch2[i]; - } - else if (opcode == OP_XOR) - { - for (unsigned int i = 0; i < vch1.size(); i++) - vch1[i] ^= vch2[i]; - } - popstack(stack); - } - break; - case OP_EQUAL: case OP_EQUALVERIFY: //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL @@ -809,8 +681,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // case OP_1ADD: case OP_1SUB: - case OP_2MUL: - case OP_2DIV: case OP_NEGATE: case OP_ABS: case OP_NOT: @@ -824,8 +694,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co { case OP_1ADD: bn += bnOne; break; case OP_1SUB: bn -= bnOne; break; - case OP_2MUL: bn <<= 1; break; - case OP_2DIV: bn >>= 1; break; case OP_NEGATE: bn = -bn; break; case OP_ABS: if (bn < bnZero) bn = -bn; break; case OP_NOT: bn = (bn == bnZero); break; @@ -839,11 +707,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co case OP_ADD: case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_MOD: - case OP_LSHIFT: - case OP_RSHIFT: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: @@ -872,33 +735,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co bn = bn1 - bn2; break; - case OP_MUL: - if (!BN_mul(&bn, &bn1, &bn2, pctx)) - return false; - break; - - case OP_DIV: - if (!BN_div(&bn, NULL, &bn1, &bn2, pctx)) - return false; - break; - - case OP_MOD: - if (!BN_mod(&bn, &bn1, &bn2, pctx)) - return false; - break; - - case OP_LSHIFT: - if (bn2 < bnZero || bn2 > CBigNum(2048)) - return false; - bn = bn1 << bn2.getulong(); - break; - - case OP_RSHIFT: - if (bn2 < bnZero || bn2 > CBigNum(2048)) - return false; - bn = bn1 >> bn2.getulong(); - break; - case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; case OP_NUMEQUAL: bn = (bn1 == bn2); break; @@ -1007,7 +843,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fSuccess) - fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); + fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); popstack(stack); popstack(stack); @@ -1069,7 +905,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co // Check signature bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fOk) - fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); + fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); if (fOk) { isig++; @@ -1199,13 +1035,13 @@ private: // sigdata_type is (signature hash, signature, public key): typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type; std::set< sigdata_type> setValid; - CCriticalSection cs_sigcache; + boost::shared_mutex cs_sigcache; public: bool Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey) { - LOCK(cs_sigcache); + boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); sigdata_type k(hash, vchSig, pubKey); std::set<sigdata_type>::iterator mi = setValid.find(k); @@ -1223,7 +1059,7 @@ public: int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000); if (nMaxCacheSize <= 0) return; - LOCK(cs_sigcache); + boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); while (static_cast<int64>(setValid.size()) > nMaxCacheSize) { @@ -1246,7 +1082,7 @@ public: }; bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, - const CTransaction& txTo, unsigned int nIn, int nHashType) + const CTransaction& txTo, unsigned int nIn, int nHashType, int flags) { static CSignatureCache signatureCache; @@ -1271,7 +1107,9 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc if (!key.Verify(sighash, vchSig)) return false; - signatureCache.Set(sighash, vchSig, vchPubKey); + if (!(flags & SCRIPT_VERIFY_NOCACHE)) + signatureCache.Set(sighash, vchSig, vchPubKey); + return true; } @@ -1723,17 +1561,6 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTrans return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); } -bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) -{ - assert(nIn < txTo.vin.size()); - const CTxIn& txin = txTo.vin[nIn]; - if (txin.prevout.n >= txFrom.vout.size()) - return false; - const CTxOut& txout = txFrom.vout[txin.prevout.n]; - - return VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, flags, nHashType); -} - static CScript PushAll(const vector<valtype>& values) { CScript result; @@ -1772,7 +1599,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0)) + if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0)) { sigs[pubkey] = sig; break; |