Merge branch '0.4.x' into 0.5.x
authorLuke Dashjr <luke-jr+git@utopios.org>
Thu, 14 Jun 2012 18:07:11 +0000 (18:07 +0000)
committerLuke Dashjr <luke-jr+git@utopios.org>
Thu, 14 Jun 2012 18:07:11 +0000 (18:07 +0000)
Conflicts:
doc/release-process.txt
src/serialize.h

1  2 
.gitignore
doc/release-process.txt
src/main.h
src/net.cpp
src/serialize.h
src/util.cpp

diff --combined .gitignore
@@@ -1,6 -1,7 +1,7 @@@
  src/*.exe
  src/bitcoin
  src/bitcoind
+ src/test_bitcoin
  .*.swp
  *.*~*
  *.bak
  *.o
  *.patch
  .bitcoin
 +#compilation and Qt preprocessor part
 +*.qm
 +Makefile
 +bitcoin-qt
 +#resources cpp
 +qrc_*.cpp
 +#qt creator
 +*.pro.user
 +#mac specific
 +.DS_Store
 +build
diff --combined doc/release-process.txt
@@@ -1,85 -1,42 +1,85 @@@
  * update translations (ping tcatm on IRC for now)
  
  * update (commit) version in sources
 +  bitcoin-qt.pro
    src/serialize.h
    share/setup.nsi
    doc/README*
  
 -* update (commit) version in OSX app bundle
 - contrib/Bitcoin.app/Contents/Info.plist
 -
 -  * CFBundleShortVersionString should have value like 0.3.23
 -  * CFBundleVersion should have value like 323
 -
  * tag version in git
  
 -  $ git tag -a v0.3.23
 +   git tag -a v0.5.1
  
  * write release notes.  git shortlog helps a lot:
  
 -  $ git shortlog --no-merges v0.3.22..
 -
 -* create source-only archive
 -
 -  $ git archive --format=tar --prefix=bitcoin-0.3.23/ HEAD | \
 -      gzip -9c > ~/tmp/bitcoin-0.3.23-src.tar.gz 
 +   git shortlog --no-merges v0.5.0..
  
  * perform gitian builds
  
 -  * From the bitcoin source dir
 -  $ cd ../gitian-builder
 -  $ ./bin/gbuild --commit bitcoin=v0.3.23 ../bitcoin/contrib/gitian.yml
 -  $ ./bin/gbuild --commit bitcoin=v0.3.23 ../bitcoin/contrib/gitian-win32.yml
 - 
 -  Build output expected:
 -  1. linux 32-bit and 64-bit binaries + source
 -  2. windows 32-bit binary + source
 -  3. windows installer
 +  * From a directory containing the bitcoin source, gitian-builder and gitian.sigs
 +   export SIGNER=(your gitian key, ie bluematt, sipa, etc)
 +   export VERSION=0.5.1
 +   cd ./gitian-builder
 +
 +  * Fetch and build inputs:
 +   mkdir -p inputs; cd inputs/
 +   wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz
 +   wget 'http://www.openssl.org/source/openssl-1.0.1b.tar.gz'
 +   wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
 +   wget 'http://downloads.sourceforge.net/project/boost/boost/1.47.0/boost_1_47_0.tar.bz2'
 +   wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.tar.gz'
 +   cd ..
 +   ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml
 +   cp build/out/boost-win32-1.47.0-gitian.zip inputs/
 +   ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
 +   cp build/out/qt-win32-4.7.4-gitian.zip inputs/
 +
 +  * Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32:
 +   ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml
 +   ./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
 +   pushd build/out
 +   zip -r bitcoin-${VERSION}-linux-gitian.zip *
 +   mv bitcoin-${VERSION}-linux-gitian.zip ../../
 +   popd
 +   ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
 +   ./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
 +   pushd build/out
 +   zip -r bitcoin-${VERSION}-win32-gitian.zip *
 +   mv bitcoin-${VERSION}-win32-gitian.zip ../../
 +   popd
  
 -* upload builds to SF
 +  Build output expected:
 +  1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip)
 +  2. windows 32-bit binary, installer + source (bitcoin-${VERSION}-win32-gitian.zip)
 +  3. Gitian signatures (in gitian.sigs/${VERSION}[-win32]/(your gitian key)/
 +
 +* repackage gitian builds for release as stand-alone zip/tar/installer exe
 +
 +  * Linux .tar.gz:
 +   unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux
 +   tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux
 +   rm -rf bitcoin-${VERSION}-linux
 +
 +  * Windows .zip and setup.exe:
 +   unzip bitcoin-${VERSION}-win32-gitian.zip -d bitcoin-${VERSION}-win32
 +   mv bitcoin-${VERSION}-win32/bitcoin-*-setup.exe .
 +   zip -r bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win32
 +   rm -rf bitcoin-${VERSION}-win32
 +
 +* perform Mac build
 +  See this blog post for how Gavin set up his build environment and
 +  patched macdeployqt to build the OSX release:
 +    http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html
 +  qmake USE_SSL=1 USE_UPNP=1 bitcoin-qt.pro
 +  make
 +  export QTDIR=/opt/local/share/qt4  # needed to find translations/qt_*.qm files
 +  T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale)
 +  contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist  
 +
 + Build output expected:
 +  Bitcoin-Qt.dmg
 +
 +* upload builds to SourceForge
  
  * create SHA256SUMS for builds, and PGP-sign it
  
  
  * update forum version
  
 -* update wiki
 -
  * update wiki download links
  
+ * update wiki changelog: https://en.bitcoin.it/wiki/Changelog
 +* Commit your signature to gitian.sigs:
 +  pushd gitian.sigs
 +  git add ${VERSION}/${SIGNER}
 +  git add ${VERSION}-win32/${SIGNER}
 +  git commit -a
 +  git push  # Assuming you can push to the gitian.sigs tree
 +  popd
 +
 +-------------------------------------------------------------------------
 +
 +* After 3 or more people have gitian-built, repackage gitian-signed zips:
 +
 +  * From a directory containing bitcoin source, gitian.sigs and gitian zips
 +   export VERSION=0.5.1
 +   mkdir bitcoin-${VERSION}-linux-gitian
 +   pushd bitcoin-${VERSION}-linux-gitian
 +   unzip ../bitcoin-${VERSION}-linux-gitian.zip
 +   mkdir gitian
 +   cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
 +   for signer in $(ls ../gitian.sigs/${VERSION}/); do
 +     cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
 +     cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
 +   done
 +   zip -r bitcoin-${VERSION}-linux-gitian.zip *
 +   cp bitcoin-${VERSION}-linux-gitian.zip ../
 +   popd
 +   mkdir bitcoin-${VERSION}-win32-gitian
 +   pushd bitcoin-${VERSION}-win32-gitian
 +   unzip ../bitcoin-${VERSION}-win32-gitian.zip
 +   mkdir gitian
 +   cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
 +   for signer in $(ls ../gitian.sigs/${VERSION}-win32/); do
 +     cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
 +     cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
 +   done
 +   zip -r bitcoin-${VERSION}-win32-gitian.zip *
 +   cp bitcoin-${VERSION}-win32-gitian.zip ../
 +   popd
 +
 +  * Upload gitian zips to SourceForge
diff --combined src/main.h
@@@ -86,7 -86,6 +86,7 @@@ class CTxIndex
  
  void RegisterWallet(CWallet* pwalletIn);
  void UnregisterWallet(CWallet* pwalletIn);
 +bool ProcessBlock(CNode* pfrom, CBlock* pblock);
  bool CheckDiskSpace(uint64 nAdditionalBytes=0);
  FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
  FILE* AppendBlockFile(unsigned int& nFileRet);
@@@ -101,7 -100,6 +101,7 @@@ void FormatHashBuffers(CBlock* pblock, 
  bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
  bool CheckProofOfWork(uint256 hash, unsigned int nBits);
  unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
 +int GetNumBlocksOfPeers();
  bool IsInitialBlockDownload();
  std::string GetWarnings(std::string strFor);
  
@@@ -403,9 -401,6 +403,9 @@@ public
      std::vector<CTxOut> vout;
      unsigned int nLockTime;
  
 +    // Denial-of-service detection:
 +    mutable int nDoS;
 +    bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
  
      CTransaction()
      {
          vin.clear();
          vout.clear();
          nLockTime = 0;
 +        nDoS = 0;  // Denial-of-service prevention
      }
  
      bool IsNull() const
      bool IsStandard() const
      {
          BOOST_FOREACH(const CTxIn& txin, vin)
-             if (!txin.scriptSig.IsPushOnly())
+             if (txin.scriptSig.size() > 200 || !txin.scriptSig.IsPushOnly())
                  return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
          BOOST_FOREACH(const CTxOut& txout, vout)
              if (!::IsStandard(txout.scriptPubKey))
@@@ -849,9 -843,6 +849,9 @@@ public
      // memory only
      mutable std::vector<uint256> vMerkleTree;
  
 +    // Denial-of-service detection:
 +    mutable int nDoS;
 +    bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
  
      CBlock()
      {
          nNonce = 0;
          vtx.clear();
          vMerkleTree.clear();
 +        nDoS = 0;
      }
  
      bool IsNull() const
          fflush(fileout);
          if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
          {
 -#ifdef __WXMSW__
 +#ifdef WIN32
              _commit(_fileno(fileout));
  #else
              fsync(fileno(fileout));
diff --combined src/net.cpp
@@@ -10,7 -10,7 +10,7 @@@
  #include "init.h"
  #include "strlcpy.h"
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
  #include <string.h>
  #else
  #include <netinet/in.h>
@@@ -105,7 -105,7 +105,7 @@@ bool ConnectSocket(const CAddress& addr
      bool fProxy = (fUseProxy && addrConnect.IsRoutable());
      struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      u_long fNonblock = 1;
      if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
  #else
                  return false;
              }
              socklen_t nRetSize = sizeof(nRet);
 -#ifdef __WXMSW__
 +#ifdef WIN32
              if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
  #else
              if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
                  return false;
              }
          }
 -#ifdef __WXMSW__
 +#ifdef WIN32
          else if (WSAGetLastError() != WSAEISCONN)
  #else
          else
      CNode::ConnectNode immediately turns the socket back to non-blocking
      but we'll turn it back to blocking just in case
      */
 -#ifdef __WXMSW__
 +#ifdef WIN32
      fNonblock = 0;
      if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
  #else
@@@ -681,7 -681,7 +681,7 @@@ CNode* ConnectNode(CAddress addrConnect
          printf("connected %s\n", addrConnect.ToString().c_str());
  
          // Set to nonblocking
 -#ifdef __WXMSW__
 +#ifdef WIN32
          u_long nOne = 1;
          if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
              printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
@@@ -734,52 -734,6 +734,52 @@@ void CNode::Cleanup(
  }
  
  
 +std::map<unsigned int, int64> CNode::setBanned;
 +CCriticalSection CNode::cs_setBanned;
 +
 +void CNode::ClearBanned()
 +{
 +    setBanned.clear();
 +}
 +
 +bool CNode::IsBanned(unsigned int ip)
 +{
 +    bool fResult = false;
 +    CRITICAL_BLOCK(cs_setBanned)
 +    {
 +        std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
 +        if (i != setBanned.end())
 +        {
 +            int64 t = (*i).second;
 +            if (GetTime() < t)
 +                fResult = true;
 +        }
 +    }
 +    return fResult;
 +}
 +
 +bool CNode::Misbehaving(int howmuch)
 +{
 +    if (addr.IsLocal())
 +    {
 +        printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
 +        return false;
 +    }
 +
 +    nMisbehavior += howmuch;
 +    if (nMisbehavior >= GetArg("-banscore", 100))
 +    {
 +        int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
 +        CRITICAL_BLOCK(cs_setBanned)
 +            if (setBanned[addr.ip] < banTime)
 +                setBanned[addr.ip] = banTime;
 +        CloseSocketDisconnect();
 +        printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
 +        return true;
 +    }
 +    return false;
 +}
 +
  
  
  
@@@ -914,7 -868,7 +914,7 @@@ void ThreadSocketHandler2(void* parg
          if (nSelect == SOCKET_ERROR)
          {
              int nErr = WSAGetLastError();
-             if (hSocketMax > -1)
+             if (hSocketMax != INVALID_SOCKET)
              {
                  printf("socket select error %d\n", nErr);
                  for (unsigned int i = 0; i <= hSocketMax; i++)
              {
                  closesocket(hSocket);
              }
 +            else if (CNode::IsBanned(addr.ip))
 +            {
 +                printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
 +                closesocket(hSocket);
 +            }
              else
              {
                  printf("accepted connection %s\n", addr.ToString().c_str());
@@@ -1549,8 -1498,6 +1549,8 @@@ void ThreadOpenConnections2(void* parg
              BOOST_FOREACH(CNode* pnode, vNodes)
                  setConnected.insert(pnode->addr.ip & 0x0000ffff);
  
 +        int64 nANow = GetAdjustedTime();
 +
          CRITICAL_BLOCK(cs_mapAddresses)
          {
              BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
                  const CAddress& addr = item.second;
                  if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
                      continue;
 -                int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
 -                int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
 +                int64 nSinceLastSeen = nANow - addr.nTime;
 +                int64 nSinceLastTry = nANow - addr.nLastTry;
  
                  // Randomize the order in a deterministic way, putting the standard port first
                  int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
@@@ -1618,8 -1565,7 +1618,8 @@@ bool OpenNetworkConnection(const CAddre
      //
      if (fShutdown)
          return false;
 -    if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
 +    if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
 +        FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
          return false;
  
      vnThreadsRunning[1]--;
@@@ -1705,7 -1651,7 +1705,7 @@@ void ThreadMessageHandler2(void* parg
          vnThreadsRunning[2]--;
          Sleep(100);
          if (fRequestShutdown)
 -            Shutdown(NULL);
 +            StartShutdown();
          vnThreadsRunning[2]++;
          if (fShutdown)
              return;
@@@ -1723,7 -1669,7 +1723,7 @@@ bool BindListenPort(string& strError
      int nOne = 1;
      addrLocalHost.port = htons(GetListenPort());
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Initialize Windows Sockets
      WSADATA wsadata;
      int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
      setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
  #endif
  
 -#ifndef __WXMSW__
 +#ifndef WIN32
      // Allow binding if the port is still in TIME_WAIT state after
      // the program was closed and restarted.  Not an issue on windows.
      setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
  #endif
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Set to nonblocking, incoming connections will also inherit this
      if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
  #else
@@@ -1802,7 -1748,7 +1802,7 @@@ void StartNode(void* parg
      if (pnodeLocalHost == NULL)
          pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      // Get local host ip
      char pszHostName[1000] = "";
      if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
@@@ -1945,7 -1891,7 +1945,7 @@@ public
              if (closesocket(hListenSocket) == SOCKET_ERROR)
                  printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
          // Shutdown Windows Sockets
          WSACleanup();
  #endif
diff --combined src/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 = 50600;
 -static const int VERSION = 40701;
++static const int VERSION = 50601;
  static const char* pszSubVer = "";
  static const bool VERSION_IS_BETA = true;
  
diff --combined src/util.cpp
@@@ -22,6 -22,7 +22,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>
  
  using namespace std;
  using namespace boost;
@@@ -75,7 -76,7 +76,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
@@@ -119,7 -120,7 +120,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];
@@@ -193,6 -194,8 +194,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)
          }
      }
  
 -#ifdef __WXMSW__
 +#ifdef WIN32
      if (fPrintToDebugger)
      {
          static CCriticalSection cs_OutputDebugStringF;
@@@ -275,7 -278,8 +278,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)
      {
@@@ -454,6 -459,7 +457,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] = '-';
@@@ -497,144 -503,39 +500,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[(unsigned char)*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[(unsigned char)p[2]] != -1)
 +                    *pfInvalid = true;
 +                break;
 +
 +            case 3: // 4n+3 base64 characters processed: require '='
 +                if (left || p[0] != '=' || decode64_table[(unsigned char)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());
  }
  
  
@@@ -676,7 -577,7 +679,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));
@@@ -705,6 -606,10 +708,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;
  }
  
@@@ -726,6 -631,10 +729,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)
@@@ -785,7 -694,7 +788,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());
@@@ -946,20 -855,11 +949,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()