diff --git a/main.cpp b/main.cpp
index 4c8f20c..360a512 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,4 +1,5 @@
 // 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.
 
@@ -1286,8 +1287,22 @@ 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).
+
             // Verify signature
-            if (!VerifySignature(txPrev, *this, i))
+            if (!VerifySignature(txPrev, *this, i, fStrictPayToScriptHash, 0))
                 return error("ConnectInputs() : %s VerifySignature failed", GetHash().ToString().substr(0,10).c_str());
 
             // Check for conflicts
@@ -1365,7 +1380,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
@@ -3454,6 +3469,17 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
         nPrevTime = nNow;
     }
     pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << 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/main.h b/main.h
index 355ef53..4f00467 100644
--- a/main.h
+++ b/main.h
@@ -1,4 +1,5 @@
 // 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.
 
@@ -510,7 +511,7 @@ public:
     bool IsStandard() const
     {
         foreach(const CTxIn& txin, vin)
-            if (!txin.scriptSig.IsPushOnly())
+            if (!::IsStandardInput(txin.scriptSig))
                 return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
         foreach(const CTxOut& txout, vout)
             if (!::IsStandard(txout.scriptPubKey))
diff --git a/rpc.cpp b/rpc.cpp
index 90e7f15..94bc106 100644
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -1,4 +1,5 @@
 // Copyright (c) 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.
 
@@ -1378,6 +1379,17 @@ Value getwork(const Array& params, bool fHelp)
         pblock->nTime = pdata->nTime;
         pblock->nNonce = pdata->nNonce;
         pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << 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();
 
         return CheckWork(pblock, reservekey);
diff --git a/script.cpp b/script.cpp
index a85c371..0d421c3 100644
--- a/script.cpp
+++ b/script.cpp
@@ -1,4 +1,5 @@
 // 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.
 
@@ -67,7 +68,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();
@@ -152,7 +153,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;
 
@@ -766,6 +767,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:
                 {
@@ -847,6 +878,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 (...)
     {
@@ -970,6 +1004,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
@@ -1007,6 +1044,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;
@@ -1082,6 +1125,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 CScript& scriptPubKey)
 {
@@ -1145,12 +1219,14 @@ bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
 }
 
 
-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;
@@ -1176,14 +1252,14 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
 
     // 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];
@@ -1194,7 +1270,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;
 
     // Anytime a signature is successfully verified, it's proof the outpoint is spent,
diff --git a/script.h b/script.h
index da904ef..b19672b 100644
--- a/script.h
+++ b/script.h
@@ -1,4 +1,5 @@
 // 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.
 
@@ -138,7 +139,7 @@ enum opcodetype
 
     // expansion
     OP_NOP1,
-    OP_NOP2,
+    OP_CHECKHASHVERIFY,  // "crypto"
     OP_NOP3,
     OP_NOP4,
     OP_NOP5,
@@ -151,6 +152,7 @@ enum opcodetype
 
 
     // template matching params
+    OP_SCRIPTHASH = 0xfc,
     OP_PUBKEYHASH = 0xfd,
     OP_PUBKEY = 0xfe,
 
@@ -285,7 +287,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";
@@ -298,6 +300,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";
 
@@ -702,8 +705,9 @@ public:
 
 uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
 bool IsStandard(const CScript& scriptPubKey);
+bool IsStandardInput(const CScript& scriptSig);
 bool IsMine(const CScript& scriptPubKey);
 bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet);
 bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
 bool SignSignature(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);
