diff --git a/src/main.cpp b/src/main.cpp
index 1f23844..2fac727 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -880,12 +880,26 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
                     if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
                         return error("ConnectInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight);
 
+            bool fStrictPayToScriptHash = true;
+            if (fBlock)
+            {
+                // To avoid being on the short end of a block-chain split,
+                // don't do validation of pay-to-script-hash transactions
+                // until blocks with timestamps after p2shtime:
+                int64 nP2SHSwitchTime = GetArg("-p2shtime", 1332460800); // Mar 23, 2012 @ 00:00:00 UTC
+                fStrictPayToScriptHash = (pindexBlock->nTime >= nP2SHSwitchTime);
+            }
+            // if !fBlock, then always be strict-- don't accept
+            // invalid-under-new-rules pay-to-script-hash transactions into
+            // our memory pool (don't relay them, don't include them
+            // in blocks we mine).
+
             // Skip ECDSA signature verification when connecting blocks (fBlock=true)
             // before the last blockchain checkpoint. This is safe because block merkle hashes are
             // still computed and checked, and any change will be caught at the next checkpoint.
             if (!(fBlock && (nBestHeight < Checkpoints::GetTotalBlocksEstimate())))
                 // Verify signature
-                if (!VerifySignature(txPrev, *this, i))
+                if (!VerifySignature(txPrev, *this, i, fStrictPayToScriptHash, 0))
                     return DoS(100,error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str()));
 
             // Check for conflicts (double-spend)
@@ -959,7 +973,7 @@ bool CTransaction::ClientConnectInputs()
                 return false;
 
             // Verify signature
-            if (!VerifySignature(txPrev, *this, i))
+            if (!VerifySignature(txPrev, *this, i, true, 0))
                 return error("ConnectInputs() : VerifySignature failed");
 
             ///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of
@@ -2881,6 +2895,17 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
     }
     ++nExtraNonce;
     pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nTime << CBigNum(nExtraNonce);
+
+    // Put "p2sh/CHV" in the coinbase to express support for the new "Pay to Script Hash"
+    // transaction type:
+    const char* pszP2SH = "p2sh/CHV";
+    pblock->vtx[0].vin[0].scriptSig += CScript(std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH)));
+    if (pblock->vtx[0].vin[0].scriptSig.size() > 100)
+    {
+        printf("ERROR: IncrementExtraNonce() overflowed coinbase; truncating\n");
+        pblock->vtx[0].vin[0].scriptSig.resize(100);
+    }
+
     pblock->hashMerkleRoot = pblock->BuildMerkleTree();
 }
 
diff --git a/src/main.h b/src/main.h
index 3870cee..e96e271 100644
--- a/src/main.h
+++ b/src/main.h
@@ -502,7 +502,7 @@ public:
     bool IsStandard() const
     {
         BOOST_FOREACH(const CTxIn& txin, vin)
-            if (!txin.scriptSig.IsPushOnly())
+            if (!::IsStandardInput(txin.scriptSig))
                 return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
         BOOST_FOREACH(const CTxOut& txout, vout)
             if (!::IsStandard(txout.scriptPubKey))
diff --git a/src/script.cpp b/src/script.cpp
index 12d3f9e..65dfdd8 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -70,7 +70,7 @@ static inline void popstack(vector<valtype>& stack)
 }
 
 
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
+bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, bool fValidatePayToScriptHash, std::vector<unsigned char> &vchLastScript)
 {
     CAutoBN_CTX pctx;
     CScript::const_iterator pc = script.begin();
@@ -155,7 +155,7 @@ bool EvalScript(vector<vector<unsigned char> >& 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;
 
@@ -771,6 +771,36 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                 }
                 break;
 
+                case OP_CHECKHASHVERIFY:
+                {
+                    // This was OP_NOP2 in old scripts
+                    if (!fValidatePayToScriptHash)
+                        break;
+
+                    if (stack.size() < 1)
+                        return false;
+
+                    // The only stack item here is what we expect the code to hash to
+                    valtype& vchHashCheck = stacktop(-1);
+
+                    // This hashes the code with RIPEMD160(SHA256(vchLastScript))
+                    valtype vchHash(20);
+                    {
+                        uint160 hash160 = Hash160(vchLastScript);
+                        memcpy(&vchHash[0], &hash160, sizeof(hash160));
+                    }
+
+                    bool fEqual = (vchHash == vchHashCheck);
+
+                    // Don't pop anything off the stack, for backward compatibility
+
+                    if (!fEqual)
+                        // If the hash doesn't match, abort
+                        return false;
+                    // If the hash matches, we're good: act like OP_NOP2 for compatibility
+                }
+                break;
+
                 case OP_CHECKMULTISIG:
                 case OP_CHECKMULTISIGVERIFY:
                 {
@@ -852,6 +882,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
             if (stack.size() + altstack.size() > 1000)
                 return false;
         }
+
+        // Save the last code segment (from the last executed OP_CODESEPARATOR onward)
+        vchLastScript = std::vector<unsigned char>(pbegincodehash, pend);
     }
     catch (...)
     {
@@ -975,6 +1008,9 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
 
         // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
         vTemplates.push_back(CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG);
+
+        // Push-to-script-hash txn, sender provides hash of verification script, receiver provides script
+        vTemplates.push_back(CScript() << OP_SCRIPTHASH << OP_CHECKHASHVERIFY << OP_DROP);
     }
 
     // Scan templates
@@ -1012,6 +1048,12 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
                     break;
                 vSolutionRet.push_back(make_pair(opcode2, vch1));
             }
+            else if (opcode2 == OP_SCRIPTHASH)
+            {
+                if (vch1.size() != sizeof(uint160))
+                    break;
+                vSolutionRet.push_back(make_pair(opcode2, vch1));
+            }
             else if (opcode1 != opcode2 || vch1 != vch2)
             {
                 break;
@@ -1084,6 +1126,37 @@ bool IsStandard(const CScript& scriptPubKey)
     return Solver(scriptPubKey, vSolution);
 }
 
+bool IsStandardInput(const CScript& scriptSig)
+{
+    CScript::const_iterator pc = scriptSig.begin();
+    CScript::const_iterator pend = scriptSig.end();
+    CScript::const_iterator pcodesep = pend;
+    CScript::const_iterator pafter;
+    opcodetype opcode;
+
+    for ( ; pc < pend; pc = pafter)
+    {
+        pafter = pc;
+        if (!scriptSig.GetOp(pafter, opcode))
+            return false;
+        if (opcode == OP_CODESEPARATOR)
+        {
+            pcodesep = pc;
+            break;
+        }
+    }
+
+    CScript scriptSigData(scriptSig.begin(), pcodesep);
+    if (!scriptSigData.IsPushOnly())
+        return false;
+
+    if (pcodesep == pend)
+        return true;
+
+    CScript scriptSigCode(pafter, pend);
+    return IsStandard(scriptSigCode);
+}
+
 
 bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
 {
@@ -1147,12 +1220,14 @@ 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<vector<unsigned char> > stack;
-    if (!EvalScript(stack, scriptSig, txTo, nIn, nHashType))
+    std::vector<unsigned char> vchLastScript;
+    if (!EvalScript(stack, scriptSig, txTo, nIn, nHashType, fValidatePayToScriptHash, vchLastScript))
         return false;
-    if (!EvalScript(stack, scriptPubKey, txTo, nIn, nHashType))
+    if (!EvalScript(stack, scriptPubKey, txTo, nIn, nHashType, fValidatePayToScriptHash, vchLastScript))
         return false;
     if (stack.empty())
         return false;
@@ -1178,14 +1253,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];
@@ -1196,7 +1271,7 @@ 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;
diff --git a/src/script.h b/src/script.h
index e61ea2f..a4291ef 100644
--- a/src/script.h
+++ b/src/script.h
@@ -149,7 +149,7 @@ enum opcodetype
 
     // expansion
     OP_NOP1,
-    OP_NOP2,
+    OP_CHECKHASHVERIFY,  // "crypto"
     OP_NOP3,
     OP_NOP4,
     OP_NOP5,
@@ -162,6 +162,7 @@ enum opcodetype
 
 
     // template matching params
+    OP_SCRIPTHASH = 0xfc,
     OP_PUBKEYHASH = 0xfd,
     OP_PUBKEY = 0xfe,
 
@@ -296,7 +297,7 @@ inline const char* GetOpName(opcodetype opcode)
 
     // expanson
     case OP_NOP1                   : return "OP_NOP1";
-    case OP_NOP2                   : return "OP_NOP2";
+    case OP_CHECKHASHVERIFY        : return "OP_CHECKHASHVERIFY";
     case OP_NOP3                   : return "OP_NOP3";
     case OP_NOP4                   : return "OP_NOP4";
     case OP_NOP5                   : return "OP_NOP5";
@@ -309,6 +310,7 @@ inline const char* GetOpName(opcodetype opcode)
 
 
     // template matching params
+    case OP_SCRIPTHASH             : return "OP_SCRIPTHASH";
     case OP_PUBKEYHASH             : return "OP_PUBKEYHASH";
     case OP_PUBKEY                 : return "OP_PUBKEY";
 
@@ -692,12 +694,13 @@ public:
 
 
 
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType);
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, bool fValidatePayToScriptHash, std::vector<unsigned char> &vchLastScript);
 
 bool IsStandard(const CScript& scriptPubKey);
+bool IsStandardInput(const CScript& scriptSig);
 bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
 bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* pkeystore, CBitcoinAddress& addressRet);
 bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
-bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
+bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType);
 
 #endif
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 13feb86..aff21b3 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -7,8 +7,8 @@
 
 using namespace std;
 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType);
-extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType);
+extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType);
+extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, bool fValidatePayToScriptHash, int nHashType);
 
 BOOST_AUTO_TEST_SUITE(script_tests)
 
@@ -21,19 +21,21 @@ BOOST_AUTO_TEST_CASE(script_PushData)
     static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
     static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
 
+    vector<unsigned char> vchLastScript;
+
     vector<vector<unsigned char> > directStack;
-    BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0));
+    BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0, true, vchLastScript));
 
     vector<vector<unsigned char> > pushdata1Stack;
-    BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0));
+    BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0, true, vchLastScript));
     BOOST_CHECK(pushdata1Stack == directStack);
 
     vector<vector<unsigned char> > pushdata2Stack;
-    BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0));
+    BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0, true, vchLastScript));
     BOOST_CHECK(pushdata2Stack == directStack);
 
     vector<vector<unsigned char> > pushdata4Stack;
-    BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0));
+    BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0, true, vchLastScript));
     BOOST_CHECK(pushdata4Stack == directStack);
 }
 
@@ -91,15 +93,15 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
     txTo12.vout[0].nValue = 1;
 
     CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
-    BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
+    BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
     txTo12.vout[0].nValue = 2;
-    BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
+    BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
 
     CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
-    BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, 0));
+    BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, true, 0));
 
     CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
-    BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, true, 0));
 }
 
 BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
@@ -127,46 +129,46 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
     std::vector<CKey> keys;
     keys.push_back(key1); keys.push_back(key2);
     CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key1); keys.push_back(key3);
     CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key2); keys.push_back(key3);
     CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
     CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
     CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
     CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
     CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear();
     keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
     CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, true, 0));
 
     keys.clear(); // Must have signatures
     CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
-    BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, 0));
+    BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0));
 }    
 
 
