Merge branch '0.4.x' into 0.5.0.x
authorLuke Dashjr <luke-jr+git@utopios.org>
Wed, 8 Feb 2012 03:46:07 +0000 (22:46 -0500)
committerLuke Dashjr <luke-jr+git@utopios.org>
Wed, 8 Feb 2012 03:46:07 +0000 (22:46 -0500)
Conflicts:
src/bitcoinrpc.cpp

1  2 
doc/README
doc/README_windows.txt
src/headers.h
src/net.h
src/serialize.h
src/util.cpp
src/util.h
src/wallet.h

diff --combined doc/README
@@@ -1,6 -1,6 +1,6 @@@
 -Bitcoin 0.4.4 BETA
 +Bitcoin 0.5.0.4 BETA
  
- Copyright (c) 2009-2011 Bitcoin Developers
+ Copyright (c) 2009-2012 Bitcoin Developers
  Distributed under the MIT/X11 software license, see the accompanying
  file license.txt or http://www.opensource.org/licenses/mit-license.php.
  This product includes software developed by the OpenSSL Project for use in
@@@ -18,16 -18,100 +18,16 @@@ with each other, with the help of a P2
  
  Setup
  -----
 +You need the Qt4 run-time libraries to run bitcoin-qt. On Debian or Ubuntu:
 +  sudo apt-get install libqtgui4
 +
  Unpack the files into a directory and run:
 - bin/32/bitcoin (GUI, 32-bit)
 + bin/32/bitcoin-qt (GUI, 32-bit)
   bin/32/bitcoind (headless, 32-bit)
 - bin/64/bitcoin (GUI, 64-bit)
 + bin/64/bitcoin-qt (GUI, 64-bit)
   bin/64/bitcoind (headless, 64-bit)
  
  
 -Wallet Encryption
 ------------------
 -Bitcoin supports native wallet encryption so that people who steal your
 -wallet file don't automatically get access to all of your Bitcoins.
 -In order to enable this feature, chose "Encrypt Wallet" from the
 -Options menu.  You will be prompted to enter a passphrase, which
 -will be used as the key to encrypt your wallet and will be needed
 -every time you wish to send Bitcoins.  If you lose this passphrase,
 -you will lose access to spend all of the bitcoins in your wallet,
 -no one, not even the Bitcoin developers can recover your Bitcoins.
 -This means you are responsible for your own security, store your
 -passphrase in a secure location and do not forget it.
 -
 -Remember that the encryption built into bitcoin only encrypts the
 -actual keys which are required to send your bitcoins, not the full
 -wallet.  This means that someone who steals your wallet file will
 -be able to see all the addresses which belong to you, as well as the
 -relevant transactions, you are only protected from someone spending
 -your coins.
 -
 -It is recommended that you backup your wallet file before you
 -encrypt your wallet.  To do this, close the Bitcoin client and
 -copy the wallet.dat file from ~/.bitcoin/ on Linux, /Users/(user
 -name)/Application Support/Bitcoin/ on Mac OSX, and %APPDATA%/Bitcoin/
 -on Windows (that is /Users/(user name)/AppData/Roaming/Bitcoin on
 -Windows Vista and 7 and /Documents and Settings/(user name)/Application
 -Data/Bitcoin on Windows XP).  Once you have copied that file to a
 -safe location, reopen the Bitcoin client and Encrypt your wallet.
 -If everything goes fine, delete the backup and enjoy your encrypted
 -wallet.  Note that once you encrypt your wallet, you will never be
 -able to go back to a version of the Bitcoin client older than 0.4.
 -
 -Keep in mind that you are always responsible for your own security.
 -All it takes is a slightly more advanced wallet-stealing trojan which
 -installs a keylogger to steal your wallet passphrase as you enter it
 -in addition to your wallet file and you have lost all your Bitcoins.
 -Wallet encryption cannot keep you safe if you do not practice
 -good security, such as running up-to-date antivirus software, only
 -entering your wallet passphrase in the Bitcoin client and using the
 -same passphrase only as your wallet passphrase.
 -
 -
 -Technical details of wallet encryption
 ---------------------------------------
 -Wallet encryption uses AES-256-CBC to encrypt only the private keys
 -that are held in a wallet.  The keys are encrypted with a master key
 -which is entirely random.  This master key is then encrypted with
 -AES-256-CBC with a key derived from the passphrase using SHA512 and
 -OpenSSL's EVP_BytesToKey and a dynamic number of rounds determined by
 -the speed of the machine which does the initial encryption (and is
 -updated based on the speed of a computer which does a subsequent
 -passphrase change).  Although the underlying code supports multiple
 -encrypted copies of the same master key (and thus multiple passphrases)
 -the client does not yet have a method to add additional passphrases.
 -
 -At runtime, the client loads the wallet as it normally would, however
 -the keystore stores the keys in encrypted form.  When the passphrase
 -is required (to top up keypool or send coins) it will either be queried
 -by a GUI prompt, or must first be entered with the walletpassphrase
 -RPC command.  This will change the wallet to "unlocked" state where the
 -unencrypted master key is stored in memory (in the case of GUI, only for
 -long enough to complete the requested operation, in RPC, for as long as
 -is specified by the second parameter to walletpassphrase).  The wallet is
 -then locked (or can be manually locked using the walletlock RPC command)
 -and the unencrypted master key is removed from memory.
 -
 -Implementation details of wallet encryption
 --------------------------------------------
 -When the wallet is locked, calls to sendtoaddress, sendfrom, sendmany,
 -and keypoolrefill will return Error -13: "Error: Please enter the wallet 
 -passphrase with walletpassphrase first."
 -
 -When the wallet is unlocked, calls to walletpassphrase will fail.
 -
 -When a wallet is encrypted, the passphrase is required to top up the
 -keypool, thus, if the passphrase is rarely entered, it is possible that
 -keypool might run out.  In this case, the default key will be used as the
 -target for payouts for mining, and calls to getnewaddress and getaccount
 -address will return an error.  In order to prevent such cases, the keypool
 -is automatically refilled when walletpassphrase is called with a correct
 -passphrase and when topupkeypool is called (while the wallet is unlocked).
 -Note that the keypool continues to be topped up on various occasions when
 -a new key from pool is used and the wallet is unlocked (or unencrypted).
 -
 -
 -
  See the documentation at the bitcoin wiki:
    https://en.bitcoin.it/wiki/Main_Page
 -
 -... for help and more information.
 +for help and more information.
diff --combined doc/README_windows.txt
@@@ -1,6 -1,6 +1,6 @@@
 -Bitcoin 0.4.4 BETA\r
 +Bitcoin 0.5.0.4 BETA\r
  \r
- Copyright (c) 2009-2011 Bitcoin Developers\r
+ Copyright (c) 2009-2012 Bitcoin Developers\r
  Distributed under the MIT/X11 software license, see the accompanying\r
  file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
  This product includes software developed by the OpenSSL Project for use in\r
@@@ -18,7 -18,7 +18,7 @@@ with each other, with the help of a P2
  \r
  Setup\r
  -----\r
 -Unpack the files into a directory and run bitcoin.exe.\r
 +Unpack the files into a directory and run bitcoin-qt.exe.\r
  \r
  If you have Microsoft Security Essentials, you need to add bitcoin.exe to its\r
  "Excluded processes" list.  Microsoft Security Essentials->Settings tab,\r
@@@ -27,9 -27,8 +27,9 @@@ select Excluded processes, press Add, s
  The software automatically finds other nodes to connect to.  You can\r
  enable Universal Plug and Play using a menu entry or set your firewall\r
  to forward port 8333 (TCP) to your computer so you can receive\r
 -incoming connections.  Bitcoin work without incoming connections,\r
 +incoming connections.  Bitcoin works without incoming connections,\r
  but allowing incoming connections helps the Bitcoin network.\r
  \r
 -See the bitcoin wiki at:  https://en.bitcoin.it/wiki/Main_Page\r
 +See the bitcoin wiki at:\r
 +  https://en.bitcoin.it/wiki/Main_Page\r
  for more help and information.\r
diff --combined src/headers.h
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  
  #if (defined(__unix__) || defined(unix)) && !defined(USG)
  #include <sys/param.h>  // to get BSD define
  #endif
 -#ifdef __WXMAC_OSX__
 +#ifdef MAC_OSX
  #ifndef BSD
  #define BSD 1
  #endif
  #endif
 -#ifdef GUI
 -#include <wx/wx.h>
 -#include <wx/stdpaths.h>
 -#include <wx/snglinst.h>
 -#include <wx/utils.h>
 -#include <wx/clipbrd.h>
 -#include <wx/taskbar.h>
 -#endif
  #include <openssl/buffer.h>
  #include <openssl/ecdsa.h>
  #include <openssl/evp.h>
@@@ -55,7 -63,7 +55,7 @@@
  #include <deque>
  #include <map>
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
  #include <windows.h>
  #include <winsock2.h>
  #include <mswsock.h>
  #include "bignum.h"
  #include "base58.h"
  #include "main.h"
 -#ifdef GUI
 -#include "uibase.h"
 -#include "ui.h"
 +#ifdef QT_GUI
 +#include "qtui.h"
  #else
  #include "noui.h"
  #endif
 -
 -#ifdef GUI
 -#include "xpm/addressbook16.xpm"
 -#include "xpm/addressbook20.xpm"
 -#include "xpm/bitcoin16.xpm"
 -#include "xpm/bitcoin20.xpm"
 -#include "xpm/bitcoin32.xpm"
 -#include "xpm/bitcoin48.xpm"
 -#include "xpm/bitcoin80.xpm"
 -#include "xpm/check.xpm"
 -#include "xpm/send16.xpm"
 -#include "xpm/send16noshadow.xpm"
 -#include "xpm/send20.xpm"
 -#include "xpm/about.xpm"
 -#endif
diff --combined src/net.h
+++ b/src/net.h
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  #ifndef BITCOIN_NET_H
@@@ -10,7 -10,7 +10,7 @@@
  #include <boost/foreach.hpp>
  #include <openssl/rand.h>
  
 -#ifndef __WXMSW__
 +#ifndef WIN32
  #include <arpa/inet.h>
  #endif
  
@@@ -123,13 -123,6 +123,13 @@@ public
      bool fDisconnect;
  protected:
      int nRefCount;
 +
 +    // Denial-of-service detection/prevention
 +    // Key is ip address, value is banned-until-time
 +    static std::map<unsigned int, int64> setBanned;
 +    static CCriticalSection cs_setBanned;
 +    int nMisbehavior;
 +
  public:
      int64 nReleaseTime;
      std::map<uint256, CRequestTracker> mapRequests;
      // publish and subscription
      std::vector<char> vfSubscribe;
  
 -
      CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
      {
          nServices = 0;
          nStartingHeight = -1;
          fGetAddr = false;
          vfSubscribe.assign(256, false);
 +        nMisbehavior = 0;
  
          // Be shy and don't send version until we hear
          if (!fInbound)
@@@ -576,25 -569,6 +576,25 @@@ public
      void CancelSubscribe(unsigned int nChannel);
      void CloseSocketDisconnect();
      void Cleanup();
 +
 +
 +    // Denial-of-service detection/prevention
 +    // The idea is to detect peers that are behaving
 +    // badly and disconnect/ban them, but do it in a
 +    // one-coding-mistake-won't-shatter-the-entire-network
 +    // way.
 +    // IMPORTANT:  There should be nothing I can give a
 +    // node that it will forward on that will make that
 +    // node's peers drop it. If there is, an attacker
 +    // can isolate a node and/or try to split the network.
 +    // Dropping a node for sending stuff that is invalid
 +    // now but might be valid in a later version is also
 +    // dangerous, because it can cause a network split
 +    // between nodes running old code and nodes running
 +    // new code.
 +    static void ClearBanned(); // needed for unit testing
 +    static bool IsBanned(unsigned int ip);
 +    bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
  };
  
  
diff --combined src/serialize.h
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  #ifndef BITCOIN_SERIALIZE_H
@@@ -30,8 -30,7 +30,8 @@@ typedef unsigned long long  uint64
  #define for  if (false) ; else for
  #endif
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
 +#include <windows.h>
  // This is used to attempt to keep keying material out of swap
  // Note that VirtualLock does not provide this as a guarantee on Windows,
  // but, in practice, memory that has been VirtualLock'd almost never gets written to
@@@ -60,7 -59,7 +60,7 @@@ class CDataStream
  class CAutoFile;
  static const unsigned int MAX_SIZE = 0x02000000;
  
 -static const int VERSION = 40400;
 +static const int VERSION = 50004;
  static const char* pszSubVer = "";
  static const bool VERSION_IS_BETA = true;
  
diff --combined src/util.cpp
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  #include "headers.h"
@@@ -64,7 -64,7 +64,7 @@@ public
              ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
          CRYPTO_set_locking_callback(locking_callback);
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
          // Seed random number generator with screen scrape and other hardware sources
          RAND_screen();
  #endif
@@@ -108,7 -108,7 +108,7 @@@ void RandAddSeedPerfmon(
          return;
      nLastPerfmon = GetTime();
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
      // Seed with the entire set of perfmon data
      unsigned char pdata[250000];
@@@ -198,7 -198,7 +198,7 @@@ inline int OutputDebugStringF(const cha
          }
      }
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      if (fPrintToDebugger)
      {
          static CCriticalSection cs_OutputDebugStringF;
@@@ -264,7 -264,8 +264,7 @@@ int my_snprintf(char* buffer, size_t li
      return ret;
  }
  
 -
 -string strprintf(const char* format, ...)
 +string strprintf(const std::string &format, ...)
  {
      char buffer[50000];
      char* p = buffer;
      {
          va_list arg_ptr;
          va_start(arg_ptr, format);
 -        ret = _vsnprintf(p, limit, format, arg_ptr);
 +        ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
          va_end(arg_ptr);
          if (ret >= 0 && ret < limit)
              break;
      return str;
  }
  
 -
 -bool error(const char* format, ...)
 +bool error(const std::string &format, ...)
  {
      char buffer[50000];
      int limit = sizeof(buffer);
      va_list arg_ptr;
      va_start(arg_ptr, format);
 -    int ret = _vsnprintf(buffer, limit, format, arg_ptr);
 +    int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
      va_end(arg_ptr);
      if (ret < 0 || ret >= limit)
      {
@@@ -443,6 -445,7 +443,6 @@@ vector<unsigned char> ParseHex(const st
      return ParseHex(str.c_str());
  }
  
 -
  void ParseParameters(int argc, char* argv[])
  {
      mapArgs.clear();
              pszValue = strchr(psz, '=');
              *pszValue++ = '\0';
          }
 -        #ifdef __WXMSW__
 +        #ifdef WIN32
          _strlwr(psz);
          if (psz[0] == '/')
              psz[0] = '-';
@@@ -486,144 -489,39 +486,144 @@@ bool SoftSetArg(const std::string& strA
  }
  
  
 +string EncodeBase64(const unsigned char* pch, size_t len)
 +{
 +    static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 +
 +    string strRet="";
 +    strRet.reserve((len+2)/3*4);
 +
 +    int mode=0, left=0;
 +    const unsigned char *pchEnd = pch+len;
  
 -const char* wxGetTranslation(const char* pszEnglish)
 +    while (pch<pchEnd)
 +    {
 +        int enc = *(pch++);
 +        switch (mode)
 +        {
 +            case 0: // we have no bits
 +                strRet += pbase64[enc >> 2];
 +                left = (enc & 3) << 4;
 +                mode = 1;
 +                break;
 +
 +            case 1: // we have two bits
 +                strRet += pbase64[left | (enc >> 4)];
 +                left = (enc & 15) << 2;
 +                mode = 2;
 +                break;
 +
 +            case 2: // we have four bits
 +                strRet += pbase64[left | (enc >> 6)];
 +                strRet += pbase64[enc & 63];
 +                mode = 0;
 +                break;
 +        }
 +    }
 +
 +    if (mode)
 +    {
 +        strRet += pbase64[left];
 +        strRet += '=';
 +        if (mode == 1)
 +            strRet += '=';
 +    }
 +
 +    return strRet;
 +}
 +
 +string EncodeBase64(const string& str)
  {
 -#ifdef GUI
 -    // Wrapper of wxGetTranslation returning the same const char* type as was passed in
 -    static CCriticalSection cs;
 -    CRITICAL_BLOCK(cs)
 +    return EncodeBase64((const unsigned char*)str.c_str(), str.size());
 +}
 +
 +vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
 +{
 +    static const int decode64_table[256] =
 +    {
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
 +        -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
 +        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
 +        29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
 +        49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 +        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 +    };
 +
 +    if (pfInvalid)
 +        *pfInvalid = false;
 +
 +    vector<unsigned char> vchRet;
 +    vchRet.reserve(strlen(p)*3/4);
 +
 +    int mode = 0;
 +    int left = 0;
 +
 +    while (1)
      {
 -        // Look in cache
 -        static map<string, char*> mapCache;
 -        map<string, char*>::iterator mi = mapCache.find(pszEnglish);
 -        if (mi != mapCache.end())
 -            return (*mi).second;
 -
 -        // wxWidgets translation
 -        wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8));
 -
 -        // We don't cache unknown strings because caller might be passing in a
 -        // dynamic string and we would keep allocating memory for each variation.
 -        if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0)
 -            return pszEnglish;
 -
 -        // Add to cache, memory doesn't need to be freed.  We only cache because
 -        // we must pass back a pointer to permanently allocated memory.
 -        char* pszCached = new char[strlen(strTranslated.utf8_str())+1];
 -        strcpy(pszCached, strTranslated.utf8_str());
 -        mapCache[pszEnglish] = pszCached;
 -        return pszCached;
 +         int dec = decode64_table[*p];
 +         if (dec == -1) break;
 +         p++;
 +         switch (mode)
 +         {
 +             case 0: // we have no bits and get 6
 +                 left = dec;
 +                 mode = 1;
 +                 break;
 +
 +              case 1: // we have 6 bits and keep 4
 +                  vchRet.push_back((left<<2) | (dec>>4));
 +                  left = dec & 15;
 +                  mode = 2;
 +                  break;
 +
 +             case 2: // we have 4 bits and get 6, we keep 2
 +                 vchRet.push_back((left<<4) | (dec>>2));
 +                 left = dec & 3;
 +                 mode = 3;
 +                 break;
 +
 +             case 3: // we have 2 bits and get 6
 +                 vchRet.push_back((left<<6) | dec);
 +                 mode = 0;
 +                 break;
 +         }
      }
 -    return NULL;
 -#else
 -    return pszEnglish;
 -#endif
 +
 +    if (pfInvalid)
 +        switch (mode)
 +        {
 +            case 0: // 4n base64 characters processed: ok
 +                break;
 +
 +            case 1: // 4n+1 base64 character processed: impossible
 +                *pfInvalid = true;
 +                break;
 +
 +            case 2: // 4n+2 base64 characters processed: require '=='
 +                if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1)
 +                    *pfInvalid = true;
 +                break;
 +
 +            case 3: // 4n+3 base64 characters processed: require '='
 +                if (left || p[0] != '=' || decode64_table[p[1]] != -1)
 +                    *pfInvalid = true;
 +                break;
 +        }
 +
 +    return vchRet;
 +}
 +
 +string DecodeBase64(const string& str)
 +{
 +    vector<unsigned char> vchRet = DecodeBase64(str.c_str());
 +    return string((const char*)&vchRet[0], vchRet.size());
  }
  
  
@@@ -665,7 -563,7 +665,7 @@@ bool WildcardMatch(const string& str, c
  
  void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
  {
 -#ifdef __WXMSW__
 +#ifdef WIN32
      char pszModule[MAX_PATH];
      pszModule[0] = '\0';
      GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
@@@ -694,6 -592,10 +694,6 @@@ void PrintException(std::exception* pex
      printf("\n\n************************\n%s\n", pszMessage);
      fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
      strMiscWarning = pszMessage;
 -#ifdef GUI
 -    if (wxTheApp && !fDaemon)
 -        MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR);
 -#endif
      throw;
  }
  
@@@ -715,6 -617,10 +715,6 @@@ void PrintExceptionContinue(std::except
      printf("\n\n************************\n%s\n", pszMessage);
      fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
      strMiscWarning = pszMessage;
 -#ifdef GUI
 -    if (wxTheApp && !fDaemon)
 -        boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage)));
 -#endif
  }
  
  
  
  
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
  typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
  
  string MyGetSpecialFolderPath(int nFolder, bool fCreate)
@@@ -765,7 -671,7 +765,7 @@@ string GetDefaultDataDir(
      // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
      // Mac: ~/Library/Application Support/Bitcoin
      // Unix: ~/.bitcoin
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Windows
      return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
  #else
      string strHome = pszHome;
      if (strHome[strHome.size()-1] != '/')
          strHome += '/';
 -#ifdef __WXMAC_OSX__
 +#ifdef MAC_OSX
      // Mac
      strHome += "Library/Application Support/";
      filesystem::create_directory(strHome.c_str());
@@@ -926,20 -832,11 +926,20 @@@ void ShrinkDebugFile(
  //  - Median of other nodes's clocks
  //  - The user (asking the user to fix the system clock if the first two disagree)
  //
 +static int64 nMockTime = 0;  // For unit testing
 +
  int64 GetTime()
  {
 +    if (nMockTime) return nMockTime;
 +
      return time(NULL);
  }
  
 +void SetMockTime(int64 nMockTimeIn)
 +{
 +    nMockTime = nMockTimeIn;
 +}
 +
  static int64 nTimeOffset = 0;
  
  int64 GetAdjustedTime()
diff --combined src/util.h
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  #ifndef BITCOIN_UTIL_H
@@@ -7,7 -7,7 +7,7 @@@
  
  #include "uint256.h"
  
 -#ifndef __WXMSW__
 +#ifndef WIN32
  #include <sys/types.h>
  #include <sys/time.h>
  #include <sys/resource.h>
@@@ -65,7 -65,7 +65,7 @@@ typedef unsigned long long  uint64
  #endif
  
  // This is needed because the foreach macro can't get over the comma in pair<t1, t2>
 -#define PAIRTYPE(t1, t2)    pair<t1, t2>
 +#define PAIRTYPE(t1, t2)    std::pair<t1, t2>
  
  // Align by increasing pointer, must have extra space at end of buffer
  template <size_t nBytes, typename T>
@@@ -81,7 -81,7 +81,7 @@@ T* alignup(T* p
      return u.ptr;
  }
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
  #define MSG_NOSIGNAL        0
  #define MSG_DONTWAIT        0
  #ifndef UINT64_MAX
@@@ -123,7 -123,7 +123,7 @@@ inline int myclosesocket(SOCKET& hSocke
  {
      if (hSocket == INVALID_SOCKET)
          return WSAENOTSOCK;
 -#ifdef __WXMSW__
 +#ifdef WIN32
      int ret = closesocket(hSocket);
  #else
      int ret = close(hSocket);
      return ret;
  }
  #define closesocket(s)      myclosesocket(s)
 -
 -#ifndef GUI
 +#if !defined(QT_GUI)
  inline const char* _(const char* psz)
  {
      return psz;
  
  
  
 -
  extern std::map<std::string, std::string> mapArgs;
  extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
  extern bool fDebug;
@@@ -167,8 -169,8 +167,8 @@@ void RandAddSeed()
  void RandAddSeedPerfmon();
  int OutputDebugStringF(const char* pszFormat, ...);
  int my_snprintf(char* buffer, size_t limit, const char* format, ...);
 -std::string strprintf(const char* format, ...);
 -bool error(const char* format, ...);
 +std::string strprintf(const std::string &format, ...);
 +bool error(const std::string &format, ...);
  void LogException(std::exception* pex, const char* pszThread);
  void PrintException(std::exception* pex, const char* pszThread);
  void PrintExceptionContinue(std::exception* pex, const char* pszThread);
@@@ -178,10 -180,6 +178,10 @@@ bool ParseMoney(const std::string& str
  bool ParseMoney(const char* pszIn, int64& nRet);
  std::vector<unsigned char> ParseHex(const char* psz);
  std::vector<unsigned char> ParseHex(const std::string& str);
 +std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
 +std::string DecodeBase64(const std::string& str);
 +std::string EncodeBase64(const unsigned char* pch, size_t len);
 +std::string EncodeBase64(const std::string& str);
  void ParseParameters(int argc, char* argv[]);
  const char* wxGetTranslation(const char* psz);
  bool WildcardMatch(const char* psz, const char* mask);
@@@ -192,7 -190,7 +192,7 @@@ std::string GetConfigFile()
  std::string GetPidFile();
  void CreatePidFile(std::string pidFile, pid_t pid);
  void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
 -#ifdef __WXMSW__
 +#ifdef WIN32
  std::string MyGetSpecialFolderPath(int nFolder, bool fCreate);
  #endif
  std::string GetDefaultDataDir();
@@@ -201,7 -199,6 +201,7 @@@ void ShrinkDebugFile()
  int GetRandInt(int nMax);
  uint64 GetRand(uint64 nMax);
  int64 GetTime();
 +void SetMockTime(int64 nMockTimeIn);
  int64 GetAdjustedTime();
  void AddTimeData(unsigned int ip, int64 nTime);
  std::string FormatFullVersion();
@@@ -286,10 -283,6 +286,10 @@@ public
  
  
  
 +// This is exactly like std::string, but with a custom allocator.
 +// (secure_allocator<> is defined in serialize.h)
 +typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
 +
  
  
  
@@@ -394,7 -387,7 +394,7 @@@ inline void PrintHex(const std::vector<
  inline int64 GetPerformanceCounter()
  {
      int64 nCounter = 0;
 -#ifdef __WXMSW__
 +#ifdef WIN32
      QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
  #else
      timeval t;
@@@ -428,7 -421,7 +428,7 @@@ void skipspaces(T& it
  
  inline bool IsSwitchChar(char c)
  {
 -#ifdef __WXMSW__
 +#ifdef WIN32
      return c == '-' || c == '/';
  #else
      return c == '-';
@@@ -488,7 -481,7 +488,7 @@@ bool SoftSetArg(const std::string& strA
  
  inline void heapchk()
  {
 -#ifdef __WXMSW__
 +#ifdef WIN32
      /// for debugging
      //if (_heapchk() != _HEAPOK)
      //    DebugBreak();
@@@ -591,51 -584,6 +591,51 @@@ inline uint160 Hash160(const std::vecto
  }
  
  
 +// Median filter over a stream of values
 +// Returns the median of the last N numbers
 +template <typename T> class CMedianFilter
 +{
 +private:
 +    std::vector<T> vValues;
 +    std::vector<T> vSorted;
 +    int nSize;
 +public:
 +    CMedianFilter(int size, T initial_value):
 +        nSize(size)
 +    {
 +        vValues.reserve(size);
 +        vValues.push_back(initial_value);
 +        vSorted = vValues;
 +    }
 +    
 +    void input(T value)
 +    {
 +        if(vValues.size() == nSize)
 +        {
 +            vValues.erase(vValues.begin());
 +        }
 +        vValues.push_back(value);
 +
 +        vSorted.resize(vValues.size());
 +        std::copy(vValues.begin(), vValues.end(), vSorted.begin());
 +        std::sort(vSorted.begin(), vSorted.end());
 +    }
 +
 +    T median() const
 +    {
 +        int size = vSorted.size();
 +        assert(size>0);
 +        if(size & 1) // Odd number of elements
 +        {
 +            return vSorted[size/2];
 +        }
 +        else // Even number of elements
 +        {
 +            return (vSorted[size/2-1] + vSorted[size/2]) / 2;
 +        }
 +    }
 +};
 +
  
  
  
  
  // Note: It turns out we might have been able to use boost::thread
  // by using TerminateThread(boost::thread.native_handle(), 0);
 -#ifdef __WXMSW__
 +#ifdef WIN32
  typedef HANDLE pthread_t;
  
  inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)
@@@ -729,7 -677,7 +729,7 @@@ inline void ExitThread(size_t nExitCode
  
  inline bool AffinityBugWorkaround(void(*pfn)(void*))
  {
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Sometimes after a few hours affinity gets stuck on one processor
      DWORD_PTR dwProcessAffinityMask = -1;
      DWORD_PTR dwSystemAffinityMask = -1;
      return false;
  }
  
 +inline uint32_t ByteReverse(uint32_t value)
 +{
 +    value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
 +    return (value<<16) | (value>>16);
 +}
 +
  #endif
diff --combined src/wallet.h
@@@ -1,5 -1,5 +1,5 @@@
  // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2011 The Bitcoin developers
+ // 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.
  #ifndef BITCOIN_WALLET_H
@@@ -13,9 -13,6 +13,9 @@@ class CWalletTx
  class CReserveKey;
  class CWalletDB;
  
 +// A CWallet is an extension of a keystore, which also maintains a set of
 +// transactions and balances, and provides the ability to create new
 +// transactions
  class CWallet : public CCryptoKeyStore
  {
  private:
@@@ -60,19 -57,14 +60,19 @@@ public
      std::vector<unsigned char> vchDefaultKey;
  
      // keystore implementation
 +    // Adds a key to the store, and saves it to disk.
      bool AddKey(const CKey& key);
 +    // Adds a key to the store, without saving it to disk (used by LoadWallet)
      bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
 +
 +    // Adds an encrypted key to the store, and saves it to disk.
      bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
 +    // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
      bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
  
 -    bool Unlock(const std::string& strWalletPassphrase);
 -    bool ChangeWalletPassphrase(const std::string& strOldWalletPassphrase, const std::string& strNewWalletPassphrase);
 -    bool EncryptWallet(const std::string& strWalletPassphrase);
 +    bool Unlock(const SecureString& strWalletPassphrase);
 +    bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
 +    bool EncryptWallet(const SecureString& strWalletPassphrase);
  
      bool AddToWallet(const CWalletTx& wtxIn);
      bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
@@@ -82,7 -74,6 +82,7 @@@
      void ReacceptWalletTransactions();
      void ResendWalletTransactions();
      int64 GetBalance() const;
 +    int64 GetUnconfirmedBalance() const;
      bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
      bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
      bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
@@@ -252,7 -243,7 +252,7 @@@ public
      unsigned int nTimeReceived;  // time received by this node
      char fFromMe;
      std::string strFromAccount;
 -    std::vector<char> vfSpent;
 +    std::vector<char> vfSpent; // which outputs are already spent
  
      // memory only
      mutable char fDebitCached;
          return fReturn;
      }
  
 +    // make sure balances are recalculated
      void MarkDirty()
      {
          fCreditCached = false;