Merge branch '0.6.x' of git://gitorious.org/+bitcoin-stable-developers/bitcoin/bitcoi...
authorGavin Andresen <gavinandresen@gmail.com>
Tue, 19 Jun 2012 20:34:10 +0000 (16:34 -0400)
committerGavin Andresen <gavinandresen@gmail.com>
Tue, 19 Jun 2012 20:34:10 +0000 (16:34 -0400)
15 files changed:
1  2 
bitcoin-qt.pro
src/checkpoints.cpp
src/db.cpp
src/db.h
src/key.cpp
src/key.h
src/main.cpp
src/makefile.linux-mingw
src/makefile.mingw
src/makefile.osx
src/makefile.unix
src/script.cpp
src/util.cpp
src/util.h
src/version.h

diff --combined bitcoin-qt.pro
@@@ -1,8 -1,8 +1,8 @@@
  TEMPLATE = app
  TARGET =
 -VERSION = 0.6.2.2
 +VERSION = 0.6.3.0
  INCLUDEPATH += src src/json src/qt
 -DEFINES += QT_GUI BOOST_THREAD_USE_LIB
 +DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
  CONFIG += no_include_pwd
  
  # for boost 1.37, add -mt to the boost libraries 
@@@ -83,7 -83,7 +83,7 @@@ contains(BITCOIN_NEED_QT_PLUGINS, 1) 
  # regenerate src/build.h
  !windows || contains(USE_BUILD_INFO, 1) {
      genbuild.depends = FORCE
-     genbuild.commands = cd $$PWD; share/genbuild.sh $$OUT_PWD/build/build.h
+     genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h
      genbuild.target = genbuildhook
      PRE_TARGETDEPS += genbuildhook
      QMAKE_EXTRA_TARGETS += genbuild
diff --combined src/checkpoints.cpp
@@@ -1,6 -1,6 +1,6 @@@
  // Copyright (c) 2009-2012 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 <boost/assign/list_of.hpp> // for 'map_list_of()'
  #include <boost/foreach.hpp>
@@@ -25,11 -25,14 +25,11 @@@ namespace Checkpoint
          boost::assign::map_list_of
          ( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"))
          ( 33333, uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6"))
 -        ( 68555, uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a"))
 -        ( 70567, uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a"))
          ( 74000, uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))
          (105000, uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"))
 -        (118000, uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))
          (134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
 -        (140700, uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd"))
          (168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
 +        (185333, uint256("0x00000000000002334c71b8706940c20348af897a9cfc0f1a6dab0d14d4ceb815"))
          ;
  
      bool CheckBlock(int nHeight, const uint256& hash)
diff --combined src/db.cpp
@@@ -1,7 -1,7 +1,7 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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 "db.h"
  #include "util.h"
@@@ -96,7 -96,6 +96,7 @@@ CDB::CDB(const char *pszFile, const cha
              dbenv.set_lk_max_locks(10000);
              dbenv.set_lk_max_objects(10000);
              dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
 +            dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
              dbenv.set_flags(DB_AUTO_COMMIT, 1);
              dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
              ret = dbenv.open(pathDataDir.string().c_str(),
diff --combined src/db.h
+++ b/src/db.h
@@@ -1,7 -1,7 +1,7 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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.
  #ifndef BITCOIN_DB_H
  #define BITCOIN_DB_H
  
@@@ -221,7 -221,7 +221,7 @@@ public
          if (!pdb)
              return false;
          DbTxn* ptxn = NULL;
 -        int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
 +        int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_WRITE_NOSYNC);
          if (!ptxn || ret != 0)
              return false;
          vTxn.push_back(ptxn);
diff --combined src/key.cpp
@@@ -1,14 -1,9 +1,14 @@@
  // Copyright (c) 2009-2012 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 <openssl/ec.h>
 +#include <map>
 +
  #include <openssl/ecdsa.h>
 +#include <openssl/obj_mac.h>
 +
 +#include "key.h"
 +#include "util.h"
  
  // Generate a private key from just the secret parameter
  int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
@@@ -120,264 -115,3 +120,264 @@@ err
      if (Q != NULL) EC_POINT_free(Q);
      return ret;
  }
 +
 +void CKey::SetCompressedPubKey()
 +{
 +    EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
 +    fCompressedPubKey = true;
 +}
 +
 +void CKey::Reset()
 +{
 +    fCompressedPubKey = false;
 +    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 +    if (pkey == NULL)
 +        throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
 +    fSet = false;
 +}
 +
 +CKey::CKey()
 +{
 +    Reset();
 +}
 +
 +CKey::CKey(const CKey& b)
 +{
 +    pkey = EC_KEY_dup(b.pkey);
 +    if (pkey == NULL)
 +        throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
 +    fSet = b.fSet;
 +}
 +
 +CKey& CKey::operator=(const CKey& b)
 +{
 +    if (!EC_KEY_copy(pkey, b.pkey))
 +        throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
 +    fSet = b.fSet;
 +    return (*this);
 +}
 +
 +CKey::~CKey()
 +{
 +    EC_KEY_free(pkey);
 +}
 +
 +bool CKey::IsNull() const
 +{
 +    return !fSet;
 +}
 +
 +bool CKey::IsCompressed() const
 +{
 +    return fCompressedPubKey;
 +}
 +
 +void CKey::MakeNewKey(bool fCompressed)
 +{
 +    if (!EC_KEY_generate_key(pkey))
 +        throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
 +    if (fCompressed)
 +        SetCompressedPubKey();
 +    fSet = true;
 +}
 +
 +bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
 +{
 +    const unsigned char* pbegin = &vchPrivKey[0];
 +    if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
 +        return false;
 +    fSet = true;
 +    return true;
 +}
 +
 +bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
 +{
 +    EC_KEY_free(pkey);
 +    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 +    if (pkey == NULL)
 +        throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
 +    if (vchSecret.size() != 32)
 +        throw key_error("CKey::SetSecret() : secret must be 32 bytes");
 +    BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
 +    if (bn == NULL)
 +        throw key_error("CKey::SetSecret() : BN_bin2bn failed");
 +    if (!EC_KEY_regenerate_key(pkey,bn))
 +    {
 +        BN_clear_free(bn);
 +        throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
 +    }
 +    BN_clear_free(bn);
 +    fSet = true;
 +    if (fCompressed || fCompressedPubKey)
 +        SetCompressedPubKey();
 +    return true;
 +}
 +
 +CSecret CKey::GetSecret(bool &fCompressed) const
 +{
 +    CSecret vchRet;
 +    vchRet.resize(32);
 +    const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
 +    int nBytes = BN_num_bytes(bn);
 +    if (bn == NULL)
 +        throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
 +    int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
 +    if (n != nBytes)
 +        throw key_error("CKey::GetSecret(): BN_bn2bin failed");
 +    fCompressed = fCompressedPubKey;
 +    return vchRet;
 +}
 +
 +CPrivKey CKey::GetPrivKey() const
 +{
 +    int nSize = i2d_ECPrivateKey(pkey, NULL);
 +    if (!nSize)
 +        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
 +    CPrivKey vchPrivKey(nSize, 0);
 +    unsigned char* pbegin = &vchPrivKey[0];
 +    if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
 +        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
 +    return vchPrivKey;
 +}
 +
 +bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
 +{
 +    const unsigned char* pbegin = &vchPubKey[0];
 +    if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
 +        return false;
 +    fSet = true;
 +    if (vchPubKey.size() == 33)
 +        SetCompressedPubKey();
 +    return true;
 +}
 +
 +std::vector<unsigned char> CKey::GetPubKey() const
 +{
 +    int nSize = i2o_ECPublicKey(pkey, NULL);
 +    if (!nSize)
 +        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
 +    std::vector<unsigned char> vchPubKey(nSize, 0);
 +    unsigned char* pbegin = &vchPubKey[0];
 +    if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
 +        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
 +    return vchPubKey;
 +}
 +
 +bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
 +{
 +    unsigned int nSize = ECDSA_size(pkey);
 +    vchSig.resize(nSize); // Make sure it is big enough
 +    if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
 +    {
 +        vchSig.clear();
 +        return false;
 +    }
 +    vchSig.resize(nSize); // Shrink to fit actual size
 +    return true;
 +}
 +
 +// create a compact signature (65 bytes), which allows reconstructing the used public key
 +// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
 +// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
 +//                  0x1D = second key with even y, 0x1E = second key with odd y
 +bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
 +{
 +    bool fOk = false;
 +    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
 +    if (sig==NULL)
 +        return false;
 +    vchSig.clear();
 +    vchSig.resize(65,0);
 +    int nBitsR = BN_num_bits(sig->r);
 +    int nBitsS = BN_num_bits(sig->s);
 +    if (nBitsR <= 256 && nBitsS <= 256)
 +    {
 +        int nRecId = -1;
 +        for (int i=0; i<4; i++)
 +        {
 +            CKey keyRec;
 +            keyRec.fSet = true;
 +            if (fCompressedPubKey)
 +                keyRec.SetCompressedPubKey();
 +            if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
 +                if (keyRec.GetPubKey() == this->GetPubKey())
 +                {
 +                    nRecId = i;
 +                    break;
 +                }
 +        }
 +
 +        if (nRecId == -1)
 +            throw key_error("CKey::SignCompact() : unable to construct recoverable key");
 +
 +        vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
 +        BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
 +        BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
 +        fOk = true;
 +    }
 +    ECDSA_SIG_free(sig);
 +    return fOk;
 +}
 +
 +// reconstruct public key from a compact signature
 +// This is only slightly more CPU intensive than just verifying it.
 +// If this function succeeds, the recovered public key is guaranteed to be valid
 +// (the signature is a valid signature of the given data for that key)
 +bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
 +{
 +    if (vchSig.size() != 65)
 +        return false;
 +    int nV = vchSig[0];
 +    if (nV<27 || nV>=35)
 +        return false;
 +    ECDSA_SIG *sig = ECDSA_SIG_new();
 +    BN_bin2bn(&vchSig[1],32,sig->r);
 +    BN_bin2bn(&vchSig[33],32,sig->s);
 +
 +    EC_KEY_free(pkey);
 +    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 +    if (nV >= 31)
 +    {
 +        SetCompressedPubKey();
 +        nV -= 4;
 +    }
 +    if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
 +    {
 +        fSet = true;
 +        ECDSA_SIG_free(sig);
 +        return true;
 +    }
 +    return false;
 +}
 +
 +bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
 +{
 +    // -1 = error, 0 = bad sig, 1 = good
 +    if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
 +        return false;
 +
 +    return true;
 +}
 +
 +bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
 +{
 +    CKey key;
 +    if (!key.SetCompactSignature(hash, vchSig))
 +        return false;
 +    if (GetPubKey() != key.GetPubKey())
 +        return false;
 +
 +    return true;
 +}
 +
 +bool CKey::IsValid()
 +{
 +    if (!fSet)
 +        return false;
 +
 +    bool fCompr;
 +    CSecret secret = GetSecret(fCompr);
 +    CKey key2;
 +    key2.SetSecret(secret, fCompr);
 +    return GetPubKey() == key2.GetPubKey();
 +}
diff --combined src/key.h
+++ b/src/key.h
@@@ -1,18 -1,20 +1,18 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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.
  #ifndef BITCOIN_KEY_H
  #define BITCOIN_KEY_H
  
  #include <stdexcept>
  #include <vector>
  
  #include "allocators.h"
  #include "uint256.h"
  
 +#include <openssl/ec.h> // for EC_KEY definition
 +
  // secp160k1
  // const unsigned int PRIVATE_KEY_SIZE = 192;
  // const unsigned int PUBLIC_KEY_SIZE  = 41;
@@@ -36,6 -38,9 +36,6 @@@
  // see www.keylength.com
  // script supports up to 75 for single byte push
  
 -int extern EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key);
 -int extern ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check);
 -
  class key_error : public std::runtime_error
  {
  public:
@@@ -57,50 -62,267 +57,50 @@@ protected
      bool fSet;
      bool fCompressedPubKey;
  
 -    void SetCompressedPubKey()
 -    {
 -        EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
 -        fCompressedPubKey = true;
 -    }
 +    void SetCompressedPubKey();
  
  public:
  
 -    void Reset()
 -    {
 -        fCompressedPubKey = false;
 -        pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 -        if (pkey == NULL)
 -            throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
 -        fSet = false;
 -    }
 -
 -    CKey()
 -    {
 -        Reset();
 -    }
 -
 -    CKey(const CKey& b)
 -    {
 -        pkey = EC_KEY_dup(b.pkey);
 -        if (pkey == NULL)
 -            throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
 -        fSet = b.fSet;
 -    }
 -
 -    CKey& operator=(const CKey& b)
 -    {
 -        if (!EC_KEY_copy(pkey, b.pkey))
 -            throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
 -        fSet = b.fSet;
 -        return (*this);
 -    }
 -
 -    ~CKey()
 -    {
 -        EC_KEY_free(pkey);
 -    }
 -
 -    bool IsNull() const
 -    {
 -        return !fSet;
 -    }
 +    void Reset();
  
 -    bool IsCompressed() const
 -    {
 -        return fCompressedPubKey;
 -    }
 +    CKey();
 +    CKey(const CKey& b);
  
 -    void MakeNewKey(bool fCompressed)
 -    {
 -        if (!EC_KEY_generate_key(pkey))
 -            throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
 -        if (fCompressed)
 -            SetCompressedPubKey();
 -        fSet = true;
 -    }
 +    CKey& operator=(const CKey& b);
  
 -    bool SetPrivKey(const CPrivKey& vchPrivKey)
 -    {
 -        const unsigned char* pbegin = &vchPrivKey[0];
 -        if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
 -            return false;
 -        fSet = true;
 -        return true;
 -    }
 +    ~CKey();
  
 -    bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
 -    {
 -        EC_KEY_free(pkey);
 -        pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 -        if (pkey == NULL)
 -            throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
 -        if (vchSecret.size() != 32)
 -            throw key_error("CKey::SetSecret() : secret must be 32 bytes");
 -        BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
 -        if (bn == NULL)
 -            throw key_error("CKey::SetSecret() : BN_bin2bn failed");
 -        if (!EC_KEY_regenerate_key(pkey,bn))
 -        {
 -            BN_clear_free(bn);
 -            throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
 -        }
 -        BN_clear_free(bn);
 -        fSet = true;
 -        if (fCompressed || fCompressedPubKey)
 -            SetCompressedPubKey();
 -        return true;
 -    }
 +    bool IsNull() const;
 +    bool IsCompressed() const;
  
 -    CSecret GetSecret(bool &fCompressed) const
 -    {
 -        CSecret vchRet;
 -        vchRet.resize(32);
 -        const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
 -        int nBytes = BN_num_bytes(bn);
 -        if (bn == NULL)
 -            throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
 -        int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
 -        if (n != nBytes) 
 -            throw key_error("CKey::GetSecret(): BN_bn2bin failed");
 -        fCompressed = fCompressedPubKey;
 -        return vchRet;
 -    }
 +    void MakeNewKey(bool fCompressed);
 +    bool SetPrivKey(const CPrivKey& vchPrivKey);
 +    bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
 +    CSecret GetSecret(bool &fCompressed) const;
 +    CPrivKey GetPrivKey() const;
 +    bool SetPubKey(const std::vector<unsigned char>& vchPubKey);
 +    std::vector<unsigned char> GetPubKey() const;
  
 -    CPrivKey GetPrivKey() const
 -    {
 -        int nSize = i2d_ECPrivateKey(pkey, NULL);
 -        if (!nSize)
 -            throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
 -        CPrivKey vchPrivKey(nSize, 0);
 -        unsigned char* pbegin = &vchPrivKey[0];
 -        if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
 -            throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
 -        return vchPrivKey;
 -    }
 -
 -    bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
 -    {
 -        const unsigned char* pbegin = &vchPubKey[0];
 -        if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
 -            return false;
 -        fSet = true;
 -        if (vchPubKey.size() == 33)
 -            SetCompressedPubKey();
 -        return true;
 -    }
 -
 -    std::vector<unsigned char> GetPubKey() const
 -    {
 -        int nSize = i2o_ECPublicKey(pkey, NULL);
 -        if (!nSize)
 -            throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
 -        std::vector<unsigned char> vchPubKey(nSize, 0);
 -        unsigned char* pbegin = &vchPubKey[0];
 -        if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
 -            throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
 -        return vchPubKey;
 -    }
 -
 -    bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
 -    {
 -        unsigned int nSize = ECDSA_size(pkey);
 -        vchSig.resize(nSize); // Make sure it is big enough
 -        if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
 -        {
 -            vchSig.clear();
 -            return false;
 -        }
 -        vchSig.resize(nSize); // Shrink to fit actual size
 -        return true;
 -    }
 +    bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
  
      // create a compact signature (65 bytes), which allows reconstructing the used public key
      // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
      // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
      //                  0x1D = second key with even y, 0x1E = second key with odd y
 -    bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
 -    {
 -        bool fOk = false;
 -        ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
 -        if (sig==NULL)
 -            return false;
 -        vchSig.clear();
 -        vchSig.resize(65,0);
 -        int nBitsR = BN_num_bits(sig->r);
 -        int nBitsS = BN_num_bits(sig->s);
 -        if (nBitsR <= 256 && nBitsS <= 256)
 -        {
 -            int nRecId = -1;
 -            for (int i=0; i<4; i++)
 -            {
 -                CKey keyRec;
 -                keyRec.fSet = true;
 -                if (fCompressedPubKey)
 -                    keyRec.SetCompressedPubKey();
 -                if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
 -                    if (keyRec.GetPubKey() == this->GetPubKey())
 -                    {
 -                        nRecId = i;
 -                        break;
 -                    }
 -            }
 -
 -            if (nRecId == -1)
 -                throw key_error("CKey::SignCompact() : unable to construct recoverable key");
 -
 -            vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
 -            BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
 -            BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
 -            fOk = true;
 -        }
 -        ECDSA_SIG_free(sig);
 -        return fOk;
 -    }
 +    bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
  
      // reconstruct public key from a compact signature
      // This is only slightly more CPU intensive than just verifying it.
      // If this function succeeds, the recovered public key is guaranteed to be valid
      // (the signature is a valid signature of the given data for that key)
 -    bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
 -    {
 -        if (vchSig.size() != 65)
 -            return false;
 -        int nV = vchSig[0];
 -        if (nV<27 || nV>=35)
 -            return false;
 -        ECDSA_SIG *sig = ECDSA_SIG_new();
 -        BN_bin2bn(&vchSig[1],32,sig->r);
 -        BN_bin2bn(&vchSig[33],32,sig->s);
 -
 -        EC_KEY_free(pkey);
 -        pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
 -        if (nV >= 31)
 -        {
 -            SetCompressedPubKey();
 -            nV -= 4;
 -        }
 -        if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
 -        {
 -            fSet = true;
 -            ECDSA_SIG_free(sig);
 -            return true;
 -        }
 -        return false;
 -    }
 +    bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
  
 -    bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
 -    {
 -        // -1 = error, 0 = bad sig, 1 = good
 -        if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
 -            return false;
 -        return true;
 -    }
 +    bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
  
      // Verify a compact signature
 -    bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
 -    {
 -        CKey key;
 -        if (!key.SetCompactSignature(hash, vchSig))
 -            return false;
 -        if (GetPubKey() != key.GetPubKey())
 -            return false;
 -        return true;
 -    }
 -
 -    bool IsValid()
 -    {
 -        if (!fSet)
 -            return false;
 +    bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
  
 -        bool fCompr;
 -        CSecret secret = GetSecret(fCompr);
 -        CKey key2;
 -        key2.SetSecret(secret, fCompr);
 -        return GetPubKey() == key2.GetPubKey();
 -    }
 +    bool IsValid();
  };
  
  #endif
diff --combined src/main.cpp
@@@ -1,7 -1,8 +1,8 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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 "checkpoints.h"
  #include "db.h"
  #include "net.h"
@@@ -43,7 -44,7 +44,7 @@@ map<uint256, CBlock*> mapOrphanBlocks
  multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
  
  map<uint256, CDataStream*> mapOrphanTransactions;
 -multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
 +map<uint256, map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
  
  // Constant stuff for coinbase transactions we create:
  CScript COINBASE_FLAGS;
@@@ -160,37 -161,17 +161,37 @@@ void static ResendWalletTransactions(
  // mapOrphanTransactions
  //
  
 -void AddOrphanTx(const CDataStream& vMsg)
 +bool AddOrphanTx(const CDataStream& vMsg)
  {
      CTransaction tx;
      CDataStream(vMsg) >> tx;
      uint256 hash = tx.GetHash();
      if (mapOrphanTransactions.count(hash))
 -        return;
 +        return false;
 +
 +    CDataStream* pvMsg = new CDataStream(vMsg);
  
 -    CDataStream* pvMsg = mapOrphanTransactions[hash] = new CDataStream(vMsg);
 +    // Ignore big transactions, to avoid a
 +    // send-big-orphans memory exhaustion attack. If a peer has a legitimate
 +    // large transaction with a missing parent then we assume
 +    // it will rebroadcast it later, after the parent transaction(s)
 +    // have been mined or received.
 +    // 10,000 orphans, each of which is at most 5,000 bytes big is
 +    // at most 500 megabytes of orphans:
 +    if (pvMsg->size() > 5000)
 +    {
 +        printf("ignoring large orphan tx (size: %u, hash: %s)\n", pvMsg->size(), hash.ToString().substr(0,10).c_str());
 +        delete pvMsg;
 +        return false;
 +    }
 +
 +    mapOrphanTransactions[hash] = pvMsg;
      BOOST_FOREACH(const CTxIn& txin, tx.vin)
 -        mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
 +        mapOrphanTransactionsByPrev[txin.prevout.hash].insert(make_pair(hash, pvMsg));
 +
 +    printf("stored orphan tx %s (mapsz %u)\n", hash.ToString().substr(0,10).c_str(),
 +        mapOrphanTransactions.size());
 +    return true;
  }
  
  void static EraseOrphanTx(uint256 hash)
      CDataStream(*pvMsg) >> tx;
      BOOST_FOREACH(const CTxIn& txin, tx.vin)
      {
 -        for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(txin.prevout.hash);
 -             mi != mapOrphanTransactionsByPrev.upper_bound(txin.prevout.hash);)
 -        {
 -            if ((*mi).second == pvMsg)
 -                mapOrphanTransactionsByPrev.erase(mi++);
 -            else
 -                mi++;
 -        }
 +        mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
 +        if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
 +            mapOrphanTransactionsByPrev.erase(txin.prevout.hash);
      }
      delete pvMsg;
      mapOrphanTransactions.erase(hash);
@@@ -216,7 -202,9 +217,7 @@@ unsigned int LimitOrphanTxSize(unsigne
      while (mapOrphanTransactions.size() > nMaxOrphans)
      {
          // Evict a random orphan:
 -        std::vector<unsigned char> randbytes(32);
 -        RAND_bytes(&randbytes[0], 32);
 -        uint256 randomhash(randbytes);
 +        uint256 randomhash = GetRandHash();
          map<uint256, CDataStream*>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
          if (it == mapOrphanTransactions.end())
              it = mapOrphanTransactions.begin();
@@@ -731,7 -719,7 +732,7 @@@ bool CWalletTx::AcceptWalletTransaction
      return false;
  }
  
 -bool CWalletTx::AcceptWalletTransaction() 
 +bool CWalletTx::AcceptWalletTransaction()
  {
      CTxDB txdb("r");
      return AcceptWalletTransaction(txdb);
@@@ -1142,28 -1130,17 +1143,28 @@@ bool CTransaction::ConnectInputs(MapPre
                      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);
  
 +            // Check for negative or overflow input values
 +            nValueIn += txPrev.vout[prevout.n].nValue;
 +            if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
 +                return DoS(100, error("ConnectInputs() : txin values out of range"));
 +
 +        }
 +        // The first loop above does all the inexpensive checks.
 +        // Only if ALL inputs pass do we perform expensive ECDSA signature checks.
 +        // Helps prevent CPU exhaustion attacks.
 +        for (unsigned int i = 0; i < vin.size(); i++)
 +        {
 +            COutPoint prevout = vin[i].prevout;
 +            assert(inputs.count(prevout.hash) > 0);
 +            CTxIndex& txindex = inputs[prevout.hash].first;
 +            CTransaction& txPrev = inputs[prevout.hash].second;
 +
              // Check for conflicts (double-spend)
              // This doesn't trigger the DoS code on purpose; if it did, it would make it easier
              // for an attacker to attempt to split the network.
              if (!txindex.vSpent[prevout.n].IsNull())
                  return fMiner ? false : error("ConnectInputs() : %s prev tx already used at %s", GetHash().ToString().substr(0,10).c_str(), txindex.vSpent[prevout.n].ToString().c_str());
  
 -            // Check for negative or overflow input values
 -            nValueIn += txPrev.vout[prevout.n].nValue;
 -            if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
 -                return DoS(100, error("ConnectInputs() : txin values out of range"));
 -
              // 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.
@@@ -1513,7 -1490,9 +1514,9 @@@ bool CBlock::SetBestChain(CTxDB& txdb, 
  {
      uint256 hash = GetHash();
  
-     txdb.TxnBegin();
+     if (!txdb.TxnBegin())
+         return error("SetBestChain() : TxnBegin failed");
      if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
      {
          txdb.WriteHashBestChain(hash);
                  printf("SetBestChain() : ReadFromDisk failed\n");
                  break;
              }
-             txdb.TxnBegin();
+             if (!txdb.TxnBegin()) {
+                 printf("SetBestChain() : TxnBegin 2 failed\n");
+                 break;
+             }
              // errors now are not fatal, we still did a reorganisation to a new chain in a valid way
              if (!block.SetBestChainInner(txdb, pindex))
                  break;
@@@ -1620,7 -1602,8 +1626,8 @@@ bool CBlock::AddToBlockIndex(unsigned i
      pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork();
  
      CTxDB txdb;
-     txdb.TxnBegin();
+     if (!txdb.TxnBegin())
+         return false;
      txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
      if (!txdb.TxnCommit())
          return false;
@@@ -1848,11 -1831,11 +1855,11 @@@ bool CheckDiskSpace(uint64 nAdditionalB
      if (nFreeBytesAvailable < (uint64)15000000 + nAdditionalBytes)
      {
          fShutdown = true;
-         string strMessage = _("Warning: Disk space is low  ");
+         string strMessage = _("Warning: Disk space is low");
          strMiscWarning = strMessage;
          printf("*** %s\n", strMessage.c_str());
          ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION | wxMODAL);
-         QueueShutdown();
+         StartShutdown();
          return false;
      }
      return true;
@@@ -2378,7 -2361,7 +2385,7 @@@ bool static ProcessMessage(CNode* pfrom
                      // at a time so the setAddrKnowns of the chosen nodes prevent repeats
                      static uint256 hashSalt;
                      if (hashSalt == 0)
 -                        RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
 +                        hashSalt = GetRandHash();
                      int64 hashAddr = addr.GetHash();
                      uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60));
                      hashRand = Hash(BEGIN(hashRand), END(hashRand));
              return error("message inv size() = %d", vInv.size());
          }
  
+         // find last block in inv vector
+         unsigned int nLastBlock = (unsigned int)(-1);
+         for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
+             if (vInv[vInv.size() - 1 - nInv].type == MSG_BLOCK) {
+                 nLastBlock = vInv.size() - 1 - nInv;
+                 break;
+             }
+         }
          CTxDB txdb("r");
          for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
          {
              if (fDebug)
                  printf("  got inventory: %s  %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new");
  
-             // Always request the last block in an inv bundle (even if we already have it), as it is the
-             // trigger for the other side to send further invs. If we are stuck on a (very long) side chain,
-             // this is necessary to connect earlier received orphan blocks to the chain again.
-             if (!fAlreadyHave || (inv.type == MSG_BLOCK && nInv==vInv.size()-1))
+             if (!fAlreadyHave)
                  pfrom->AskFor(inv);
-             if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
+             else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
                  pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
+             } else if (nInv == nLastBlock) {
+                 // In case we are on a very long side-chain, it is possible that we already have
+                 // the last block in an inv bundle sent in response to getblocks. Try to detect
+                 // this situation and push another getblocks to continue.
+                 std::vector<CInv> vGetData(1,inv);
+                 pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0));
+                 if (fDebug)
+                     printf("force request: %s\n", inv.ToString().c_str());
+             }
  
              // Track requests for our stuff
              Inventory(inv.hash);
      else if (strCommand == "tx")
      {
          vector<uint256> vWorkQueue;
 +        vector<uint256> vEraseQueue;
          CDataStream vMsg(vRecv);
          CTxDB txdb("r");
          CTransaction tx;
              RelayMessage(inv, vMsg);
              mapAlreadyAskedFor.erase(inv);
              vWorkQueue.push_back(inv.hash);
 +            vEraseQueue.push_back(inv.hash);
  
              // Recursively process any orphan transactions that depended on this one
              for (unsigned int i = 0; i < vWorkQueue.size(); i++)
              {
                  uint256 hashPrev = vWorkQueue[i];
 -                for (multimap<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev.lower_bound(hashPrev);
 -                     mi != mapOrphanTransactionsByPrev.upper_bound(hashPrev);
 +                for (map<uint256, CDataStream*>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin();
 +                     mi != mapOrphanTransactionsByPrev[hashPrev].end();
                       ++mi)
                  {
                      const CDataStream& vMsg = *((*mi).second);
                      CTransaction tx;
                      CDataStream(vMsg) >> tx;
                      CInv inv(MSG_TX, tx.GetHash());
 +                    bool fMissingInputs2 = false;
  
 -                    if (tx.AcceptToMemoryPool(txdb, true))
 +                    if (tx.AcceptToMemoryPool(txdb, true, &fMissingInputs2))
                      {
                          printf("   accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
                          SyncWithWallets(tx, NULL, true);
                          RelayMessage(inv, vMsg);
                          mapAlreadyAskedFor.erase(inv);
                          vWorkQueue.push_back(inv.hash);
 +                        vEraseQueue.push_back(inv.hash);
 +                    }
 +                    else if (!fMissingInputs2)
 +                    {
 +                        // invalid orphan
 +                        vEraseQueue.push_back(inv.hash);
 +                        printf("   removed invalid orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
                      }
                  }
              }
  
 -            BOOST_FOREACH(uint256 hash, vWorkQueue)
 +            BOOST_FOREACH(uint256 hash, vEraseQueue)
                  EraseOrphanTx(hash);
          }
          else if (fMissingInputs)
          {
 -            printf("storing orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
              AddOrphanTx(vMsg);
  
              // DoS prevention: do not allow mapOrphanTransactions to grow unbounded
@@@ -2819,7 -2807,7 +2840,7 @@@ bool ProcessMessages(CNode* pfrom
          unsigned int nMessageSize = hdr.nMessageSize;
          if (nMessageSize > MAX_SIZE)
          {
-             printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
+             printf("ProcessMessages(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
              continue;
          }
          if (nMessageSize > vRecv.size())
          memcpy(&nChecksum, &hash, sizeof(nChecksum));
          if (nChecksum != hdr.nChecksum)
          {
-             printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
+             printf("ProcessMessages(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
                 strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
              continue;
          }
              if (strstr(e.what(), "end of data"))
              {
                  // Allow exceptions from underlength message on vRecv
-                 printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
+                 printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
              }
              else if (strstr(e.what(), "size too large"))
              {
                  // Allow exceptions from overlong size
-                 printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
+                 printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
              }
              else
              {
-                 PrintExceptionContinue(&e, "ProcessMessage()");
+                 PrintExceptionContinue(&e, "ProcessMessages()");
              }
          }
          catch (std::exception& e) {
-             PrintExceptionContinue(&e, "ProcessMessage()");
+             PrintExceptionContinue(&e, "ProcessMessages()");
          } catch (...) {
-             PrintExceptionContinue(NULL, "ProcessMessage()");
+             PrintExceptionContinue(NULL, "ProcessMessages()");
          }
  
          if (!fRet)
@@@ -2895,7 -2883,7 +2916,7 @@@ bool SendMessages(CNode* pto, bool fSen
          if (pto->nVersion == 0)
              return true;
  
 -        // Keep-alive ping. We send a nonce of zero because we don't use it anywhere 
 +        // Keep-alive ping. We send a nonce of zero because we don't use it anywhere
          // right now.
          if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty()) {
              uint64 nonce = 0;
                      // 1/4 of tx invs blast to all immediately
                      static uint256 hashSalt;
                      if (hashSalt == 0)
 -                        RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
 +                        hashSalt = GetRandHash();
                      uint256 hashRand = inv.hash ^ hashSalt;
                      hashRand = Hash(BEGIN(hashRand), END(hashRand));
                      bool fTrickleWait = ((hashRand & 3) != 0);
@@@ -3096,7 -3084,7 +3117,7 @@@ void SHA256Transform(void* pstate, void
          ctx.h[i] = ((uint32_t*)pinit)[i];
  
      SHA256_Update(&ctx, data, sizeof(data));
 -    for (int i = 0; i < 8; i++) 
 +    for (int i = 0; i < 8; i++)
          ((uint32_t*)pstate)[i] = ctx.h[i];
  }
  
@@@ -3222,7 -3210,7 +3243,7 @@@ CBlock* CreateNewBlock(CReserveKey& res
                  dPriority += (double)nValueIn * nConf;
  
                  if (fDebug && GetBoolArg("-printpriority"))
-                     printf("priority     nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
+                     printf("priority     nValueIn=%-12"PRI64d" nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
              }
  
              // Priority is sum(valuein * age) / txsize
diff --combined src/makefile.linux-mingw
@@@ -27,7 -27,7 +27,7 @@@ LIBS= 
   -l ssl \
   -l crypto
  
 -DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
 +DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
  DEBUGFLAGS=-g
  CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
  
@@@ -69,7 -69,7 +69,7 @@@ OBJS= 
  all: bitcoind.exe
  
  obj/build.h: FORCE
-       ../share/genbuild.sh obj/build.h
+       /bin/sh ../share/genbuild.sh obj/build.h
  version.cpp: obj/build.h
  DEFS += -DHAVE_BUILD_INFO
  
diff --combined src/makefile.mingw
@@@ -7,12 -7,12 +7,12 @@@ USE_UPNP:=
  INCLUDEPATHS= \
   -I"C:\boost-1.47.0-mgw" \
   -I"C:\db-4.8.30.NC-mgw\build_unix" \
-  -I"C:\openssl-1.0.0d-mgw\include"
+  -I"C:\openssl-1.0.1b-mgw\include"
  
  LIBPATHS= \
   -L"C:\boost-1.47.0-mgw\stage\lib" \
   -L"C:\db-4.8.30.NC-mgw\build_unix" \
-  -L"C:\openssl-1.0.0d-mgw"
+  -L"C:\openssl-1.0.1b-mgw"
  
  LIBS= \
   -l boost_system-mgw45-mt-s-1_47 \
@@@ -23,7 -23,7 +23,7 @@@
   -l ssl \
   -l crypto
  
 -DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB
 +DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
  DEBUGFLAGS=-g
  CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
  
diff --combined src/makefile.osx
@@@ -53,7 -53,7 +53,7 @@@ LIBS += 
  TESTDEFS += -DBOOST_TEST_DYN_LINK
  endif
  
 -DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0
 +DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE
  
  ifdef RELEASE
  # Compile for maximum compatibility and smallest size.
@@@ -106,7 -106,7 +106,7 @@@ all: bitcoin
  -include obj-test/*.P
  
  obj/build.h: FORCE
-       ../share/genbuild.sh obj/build.h
+       /bin/sh ../share/genbuild.sh obj/build.h
  version.cpp: obj/build.h
  DEFS += -DHAVE_BUILD_INFO
  
diff --combined src/makefile.unix
@@@ -4,7 -4,7 +4,7 @@@
  
  USE_UPNP:=0
  
 -DEFS=
 +DEFS=-DBOOST_SPIRIT_THREADSAFE
  
  DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
  LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
@@@ -116,7 -116,7 +116,7 @@@ all: bitcoin
  -include obj-test/*.P
  
  obj/build.h: FORCE
-       ../share/genbuild.sh obj/build.h
+       /bin/sh ../share/genbuild.sh obj/build.h
  version.cpp: obj/build.h
  DEFS += -DHAVE_BUILD_INFO
  
diff --combined src/script.cpp
@@@ -1,9 -1,8 +1,9 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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 <boost/foreach.hpp>
 +#include <boost/tuple/tuple.hpp>
  
  using namespace std;
  using namespace boost;
@@@ -13,7 -12,6 +13,7 @@@
  #include "bignum.h"
  #include "key.h"
  #include "main.h"
 +#include "util.h"
  
  bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
  
@@@ -1101,67 -1099,12 +1101,67 @@@ uint256 SignatureHash(CScript scriptCod
  }
  
  
 +// Valid signature cache, to avoid doing expensive ECDSA signature checking
 +// twice for every transaction (once when accepted into memory pool, and
 +// again when accepted into the block chain)
 +
 +class CSignatureCache
 +{
 +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;
 +
 +public:
 +    bool
 +    Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
 +    {
 +        LOCK(cs_sigcache);
 +
 +        sigdata_type k(hash, vchSig, pubKey);
 +        std::set<sigdata_type>::iterator mi = setValid.find(k);
 +        if (mi != setValid.end())
 +            return true;
 +        return false;
 +    }
 +
 +    void
 +    Set(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
 +    {
 +        // DoS prevention: limit cache size to less than 10MB
 +        // (~200 bytes per cache entry times 50,000 entries)
 +        // Since there are a maximum of 20,000 signature operations per block
 +        // 50,000 is a reasonable default.
 +        int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
 +        if (nMaxCacheSize <= 0) return;
 +
 +        LOCK(cs_sigcache);
 +
 +        while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
 +        {
 +            // Evict a random entry. Random because that helps
 +            // foil would-be DoS attackers who might try to pre-generate
 +            // and re-use a set of valid signatures just-slightly-greater
 +            // than our cache size.
 +            uint256 randomHash = GetRandHash();
 +            std::vector<unsigned char> unused;
 +            std::set<sigdata_type>::iterator it =
 +                setValid.lower_bound(sigdata_type(randomHash, unused, unused));
 +            if (it == setValid.end())
 +                it = setValid.begin();
 +            setValid.erase(*it);
 +        }
 +
 +        sigdata_type k(hash, vchSig, pubKey);
 +        setValid.insert(k);
 +    }
 +};
 +
  bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
                const CTransaction& txTo, unsigned int nIn, int nHashType)
  {
 -    CKey key;
 -    if (!key.SetPubKey(vchPubKey))
 -        return false;
 +    static CSignatureCache signatureCache;
  
      // Hash type is one byte tacked on to the end of the signature
      if (vchSig.empty())
          return false;
      vchSig.pop_back();
  
 -    return key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig);
 +    uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType);
 +
 +    if (signatureCache.Get(sighash, vchSig, vchPubKey))
 +        return true;
 +
 +    CKey key;
 +    if (!key.SetPubKey(vchPubKey))
 +        return false;
 +
 +    if (!key.Verify(sighash, vchSig))
 +        return false;
 +
 +    signatureCache.Set(sighash, vchSig, vchPubKey);
 +    return true;
  }
  
  
diff --combined src/util.cpp
@@@ -1,7 -1,7 +1,7 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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 "util.h"
  #include "strlcpy.h"
@@@ -26,6 -26,7 +26,7 @@@ namespace boost 
  #include <boost/interprocess/sync/interprocess_mutex.hpp>
  #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
  #include <boost/foreach.hpp>
+ #include <boost/thread.hpp>
  #include <openssl/crypto.h>
  #include <openssl/rand.h>
  
@@@ -174,12 -175,6 +175,12 @@@ int GetRandInt(int nMax
      return GetRand(nMax);
  }
  
 +uint256 GetRandHash()
 +{
 +    uint256 hash;
 +    RAND_bytes((unsigned char*)&hash, sizeof(hash));
 +    return hash;
 +}
  
  
  
@@@ -215,6 -210,8 +216,8 @@@ inline int OutputDebugStringF(const cha
          if (fileout)
          {
              static bool fStartedNewLine = true;
+             static boost::mutex mutexDebugLog;
+             boost::mutex::scoped_lock scoped_lock(mutexDebugLog);
  
              // Debug print useful for profiling
              if (fLogTimestamps && fStartedNewLine)
@@@ -849,7 -846,7 +852,7 @@@ boost::filesystem::path GetDefaultDataD
  #ifdef MAC_OSX
      // Mac
      pathRet /= "Library/Application Support";
-     filesystem::create_directory(pathRet);
+     fs::create_directory(pathRet);
      return pathRet / "Bitcoin";
  #else
      // Unix
diff --combined src/util.h
@@@ -1,7 -1,7 +1,7 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2012 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.
  #ifndef BITCOIN_UTIL_H
  #define BITCOIN_UTIL_H
  
@@@ -168,7 -168,6 +168,7 @@@ bool SetStartOnSystemStartup(bool fAuto
  void ShrinkDebugFile();
  int GetRandInt(int nMax);
  uint64 GetRand(uint64 nMax);
 +uint256 GetRandHash();
  int64 GetTime();
  void SetMockTime(int64 nMockTimeIn);
  int64 GetAdjustedTime();
@@@ -218,9 -217,11 +218,11 @@@ public
              {
                  printf("LOCKCONTENTION: %s\n", pszName);
                  printf("Locker: %s:%d\n", pszFile, nLine);
-             }
  #endif
              lock.lock();
+ #ifdef DEBUG_LOCKCONTENTION
+             }
+ #endif
          }
      }
  
diff --combined src/version.h
@@@ -1,6 -1,6 +1,6 @@@
  // Copyright (c) 2012 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.
  #ifndef BITCOIN_VERSION_H
  #define BITCOIN_VERSION_H
  
  // client versioning
  //
  
- static const int CLIENT_VERSION_MAJOR       =  0;
- static const int CLIENT_VERSION_MINOR       =  6;
- static const int CLIENT_VERSION_REVISION    =  3;
- static const int CLIENT_VERSION_BUILD       = 0;
+ // These need to be macro's, as version.cpp's voodoo requires it
+ #define CLIENT_VERSION_MAJOR       0
+ #define CLIENT_VERSION_MINOR       6
 -#define CLIENT_VERSION_REVISION    2
 -#define CLIENT_VERSION_BUILD       2
++#define CLIENT_VERSION_REVISION    3
++#define CLIENT_VERSION_BUILD       0
  
  static const int CLIENT_VERSION =
                             1000000 * CLIENT_VERSION_MAJOR