X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fscript.cpp;h=942ddc84a97e5c9f274c1524f8da254b76c0656b;hb=bfb1d91d910f8a27ca3ef1a60c8026a3e08b3f9e;hp=26b7c941f428169e910ccea6c0dbe8ae239712c4;hpb=e5e4c598dc43bb5e01b3a30aaeb2dfc9376bd7b4;p=novacoin.git diff --git a/src/script.cpp b/src/script.cpp index 26b7c94..942ddc8 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -148,6 +148,7 @@ const char* GetOpName(opcodetype opcode) case OP_ENDIF : return "OP_ENDIF"; case OP_VERIFY : return "OP_VERIFY"; case OP_RETURN : return "OP_RETURN"; + case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY"; // stack ops case OP_TOALTSTACK : return "OP_TOALTSTACK"; @@ -230,7 +231,6 @@ const char* GetOpName(opcodetype opcode) // expanson case OP_NOP1 : return "OP_NOP1"; - case OP_NOP2 : return "OP_NOP2"; case OP_NOP3 : return "OP_NOP3"; case OP_NOP4 : return "OP_NOP4"; case OP_NOP5 : return "OP_NOP5"; @@ -294,7 +294,7 @@ bool IsDERSignature(const valtype &vchSig, bool fWithHashType, bool fCheckLow) { if (5 + nLenR >= vchSig.size()) return error("Non-canonical signature: S length misplaced"); unsigned int nLenS = vchSig[5+nLenR]; - if ((unsigned long)(nLenR + nLenS + (fWithHashType ? 7 : 6)) != vchSig.size()) + if ((nLenR + nLenS + (fWithHashType ? 7 : 6)) != vchSig.size()) return error("Non-canonical signature: R+S length mismatch"); const unsigned char *R = &vchSig[4]; @@ -422,7 +422,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // Control // case OP_NOP: - case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: + case OP_NOP1: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; @@ -481,6 +481,43 @@ bool EvalScript(vector >& stack, const CScript& script, co } break; + case OP_CHECKLOCKTIMEVERIFY: + { + // CHECKLOCKTIMEVERIFY + // + // (nLockTime -- nLockTime) + if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) + break; // treat as a NOP is not enabled + if (stack.size() < 1) + return false; + const CBigNum nLockTime = CastToBigNum(stacktop(-1)); + if (nLockTime < 0) + return false; // Negative argument is senseless. + + if (!( // We can have either lock-by-blockheight or lock-by-blocktime. + (txTo.nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) || + (txTo.nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD) + )) + return false; + + // Now we can perform a simple numerical comparison + 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 (txTo.vin[nIn].IsFinal()) + return false; + break; + } // // Stack ops @@ -1195,7 +1232,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector SMALLDATA_SWITCH_TIME) + if (fTestNet || GetTime() > SMALLDATA_SWITCH_TIME) { // Malleable pubkey tx hack, sender provides generated pubkey combined with R parameter. The R parameter is dropped before checking a signature. mTemplates.insert(make_pair(TX_PUBKEY_DROP, CScript() << OP_PUBKEY << OP_PUBKEY << OP_DROP << OP_CHECKSIG)); @@ -1211,6 +1248,8 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) { + typeRet = TX_NULL_DATA; + return true; + } + // Scan templates const CScript& script1 = scriptPubKey; BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates) @@ -1507,14 +1556,9 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) case TX_PUBKEY_DROP: { CPubKey key = CPubKey(vSolutions[0]); - if (keystore.HaveKey(key.GetID())) + CPubKey R = CPubKey(vSolutions[1]); + if (keystore.CheckOwnership(key, R)) return MINE_SPENDABLE; - else - { - CPubKey R = CPubKey(vSolutions[1]); - if (keystore.CheckOwnership(key, R)) - return MINE_SPENDABLE; - } } break; case TX_PUBKEYHASH: @@ -1559,7 +1603,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) if (!Solver(scriptPubKey, whichType, vSolutions)) return false; - if (whichType == TX_PUBKEY || whichType == TX_PUBKEY_DROP) + if (whichType == TX_PUBKEY) { addressRet = CPubKey(vSolutions[0]).GetID(); return true; @@ -1624,7 +1668,10 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto if (!Solver(scriptPubKey, typeRet, vSolutions)) return false; if (typeRet == TX_NULL_DATA) + { + nRequiredRet = 0; return true; + } if (typeRet == TX_MULTISIG) { @@ -1638,6 +1685,8 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto else { nRequiredRet = 1; + if (typeRet == TX_PUBKEY_DROP) + return true; CTxDestination address; if (!ExtractDestination(scriptPubKey, address)) return false; @@ -1972,6 +2021,13 @@ void CScript::SetDestination(const CTxDestination& dest) boost::apply_visitor(CScriptVisitor(this), dest); } +void CScript::SetDestination(const CPubKey& R, CPubKey& pubKeyVariant) +{ + this->clear(); + *this << pubKeyVariant << R << OP_DROP << OP_CHECKSIG; +} + + void CScript::SetMultisig(int nRequired, const std::vector& keys) { this->clear();