Satoshi MailBeta Open in Satoshi Mail

unix build merged in, bitmap resources from xpm instead of rc, better addr relay, better selection of addrs by time last seen for faster connect

Commit by Satoshi Nakamoto (s_nakamoto) on 5 November 2009 · SVN r32 · release v0.2.0 · 23 files, +2,184 −301

Open in Satoshi Mail View on GitHub

Files changed

build-unix.txt
@@ -0,0 +1,73 @@
+Bitcoin v0.2.0 BETA
+
+Copyright (c) 2009 Satoshi Nakamoto
+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
+the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
+cryptographic software written by Eric Young (eay@cryptsoft.com).
+
+
+UNIX BUILD NOTES
+
+
+Dependencies
+------------
+apt-get install build-essential
+apt-get install libgtk2.0-dev
+apt-get install libssl-dev
+
+Libraries you need to obtain separately and build:
+              default path   download
+wxWidgets      \wxwidgets     http://www.wxwidgets.org/downloads/
+Berkeley DB    \db            http://www.oracle.com/technology/software/products/berkeley-db/index.html
+Boost          \boost         http://www.boost.org/users/download/
+
+Their licenses:
+wxWidgets      LGPL 2.1 with very liberal exceptions
+Berkeley DB    New BSD license with additional requirement that linked software must be free open source
+Boost          MIT-like license
+
+Versions used in this release:
+GCC          4.3.3
+OpenSSL      0.9.8k
+wxWidgets    2.8.9
+Berkeley DB  4.7.25.NC
+Boost        1.40.0
+
+
+Notes
+-----
+The UI layout is edited with wxFormBuilder.  Open the project file
+uiproject.fbp.  It generates uibase.cpp and uibase.h, which define base
+classes that do the rote work of constructing all the UI elements.
+
+The release is built with GCC and then "strip bitcoin" to strip the debug
+symbols, which reduces the executable size by about 90%.
+
+
+wxWidgets
+---------
+cd /usr/local/wxWidgets-2.8.9
+mkdir buildgtk
+cd buildgtk
+../configure --with-gtk --enable-debug --disable-shared --enable-monolithic
+make
+su
+make install
+ldconfig
+
+
+Berkeley DB
+-----------
+cd /usr/local/db-4.7.25.NC/build_unix
+../dist/configure --enable-cxx
+make
+
+
+Boost
+-----
+cd /usr/local/boost_1_40_0
+su
+./bootstrap.sh
+./bjam install
build.txt
@@ -1,88 +0,0 @@
-BitCoin v0.1.6 BETA
-
-Copyright (c) 2009 Satoshi Nakamoto
-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
-the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
-cryptographic software written by Eric Young (eay@cryptsoft.com).
-
-
-Compilers Supported
--------------------
-MinGW GCC (v3.4.5)
-Microsoft Visual C++ 6.0 SP6
-
-
-Dependencies
-------------
-Libraries you need to obtain separately to build:
-
-              default path   download
-wxWidgets      \wxwidgets     http://www.wxwidgets.org/downloads/
-                                or prebuilt: http://wxpack.sourceforge.net
-OpenSSL        \openssl       http://www.openssl.org/source/
-Berkeley DB    \db            http://www.oracle.com/technology/software/products/berkeley-db/index.html
-Boost          \boost         http://www.boost.org/users/download/
-
-Their licenses:
-wxWidgets      LGPL 2.1 with very liberal exceptions
-OpenSSL        Old BSD license with the problematic advertising requirement
-Berkeley DB    New BSD license with additional requirement that linked software must be free open source
-Boost          MIT-like license
-
-
-Notes
------
-The UI layout is edited with wxFormBuilder.  Open the project file
-uiproject.fbp.  It generates uibase.cpp and uibase.h, which define base
-classes that do the rote work of constructing all the UI elements.
-
-The release is built with GCC and then "strip bitcoin.exe" to strip the debug
-symbols, which reduces the executable size by about 90%.
-
-
-OpenSSL
--------
-Bitcoin does not use any encryption.  If you want to do a no-everything
-build of OpenSSL to exclude encryption routines, a few patches are required.
-(OpenSSL v0.9.8h)
-
-Edit engines\e_gmp.c and put this #ifndef around #include <openssl/rsa.h>
-  #ifndef OPENSSL_NO_RSA
-  #include <openssl/rsa.h>
-  #endif
-
-Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line:
-  void ERR_load_RSA_strings(void) { }
-
-Edit ms\mingw32.bat and replace the Configure line's parameters with this
-no-everything list.  You have to put this in the batch file because batch
-files can't take more than 9 command line parameters.
-  perl Configure mingw threads no-rc2 no-rc4 no-rc5 no-idea no-des no-bf no-cast no-aes no-camellia no-seed no-rsa no-dh
-
-Also REM out the following line in ms\mingw32.bat.  The build fails after it's
-already finished building libeay32, which is all we care about, but the
-failure aborts the script before it runs dllwrap to generate libeay32.dll.
-  REM  if errorlevel 1 goto end
-
-Build
-  ms\mingw32.bat
-
-If you want to use it with MSVC, generate the .lib file
-  lib /machine:i386 /def:ms\libeay32.def /out:out\libeay32.lib
-
-
-Berkeley DB
------------
-Using MinGW and MSYS:
-cd \db\build_unix
-sh ../dist/configure --enable-mingw --enable-cxx
-make
-
-
-Boost
------
-If you have trouble compiling Boost with Microsoft Visual C++ 6.0, try going
-back to Boost version 1.35.  It looks like they may be starting to reduce
-support for MSVC 6.0.
db.cpp
@@ -62,9 +62,9 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
             if (fShutdown)
                 return;
             string strDataDir = GetDataDir();
-            string strLogDir = strDataDir + "\\database";
+            string strLogDir = strDataDir + "/database";
             _mkdir(strLogDir.c_str());
-            string strErrorFile = strDataDir + "\\db.log";
+            string strErrorFile = strDataDir + "/db.log";
             printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
 
             dbenv.set_lg_dir(strLogDir.c_str());
@@ -411,7 +411,6 @@ bool CAddrDB::WriteAddress(const CAddress& addr)
 
 bool CAddrDB::LoadAddresses()
 {
-    CRITICAL_BLOCK(cs_mapIRCAddresses)
     CRITICAL_BLOCK(cs_mapAddresses)
     {
         // Load user provided addresses
@@ -425,10 +424,7 @@ bool CAddrDB::LoadAddresses()
                 {
                     CAddress addr(psz, NODE_NETWORK);
                     if (addr.IsValid())
-                    {
                         AddAddress(*this, addr);
-                        mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
-                    }
                 }
             }
             catch (...) { }
@@ -678,7 +674,7 @@ void ThreadFlushWalletDB(void* parg)
                     if (nRefCount == 0 && !fShutdown)
                     {
                         // Flush wallet.dat so it's self contained
-                        nLastFlushed == nWalletDBUpdated;
+                        nLastFlushed = nWalletDBUpdated;
                         int64 nStart = GetTimeMillis();
                         dbenv.txn_checkpoint(0, 0, 0);
                         dbenv.lsn_reset(strFile.c_str(), 0);
headers.h
@@ -17,16 +17,18 @@
 #endif
 #define _WIN32_IE 0x0400
 #define WIN32_LEAN_AND_MEAN 1
+#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
 #include <wx/wx.h>
 #include <wx/clipbrd.h>
 #include <wx/snglinst.h>
 #include <wx/taskbar.h>
 #include <wx/stdpaths.h>
+#include <wx/utils.h>
 #include <openssl/ecdsa.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <openssl/sha.h>
-#include <openssl/ripemd.h>
+#include <openssl/ripemd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
@@ -50,22 +52,28 @@
 #include <boost/tuple/tuple.hpp>
 #include <boost/tuple/tuple_comparison.hpp>
 #include <boost/tuple/tuple_io.hpp>
-#include <boost/array.hpp>
-
+#include <boost/array.hpp>
+
 #ifdef __WXMSW__
 #include <windows.h>
 #include <winsock2.h>
-#include <mswsock.h>
+#include <mswsock.h>
 #include <shlobj.h>
-#include <shlwapi.h>
-#include <io.h>
-#include <process.h>
-#else
+#include <shlwapi.h>
+#include <io.h>
+#include <process.h>
+#else
 #include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <boost/filesystem.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/algorithm/string.hpp>
+#endif
 
 #pragma hdrstop
 using namespace std;
@@ -88,3 +96,11 @@ using namespace boost;
 #include "market.h"
 #include "uibase.h"
 #include "ui.h"
+
+#include "xpm/addressbook16.xpm"
+#include "xpm/addressbook20.xpm"
+#include "xpm/bitcoin.xpm"
+#include "xpm/check.xpm"
+#include "xpm/send16.xpm"
+#include "xpm/send16noshadow.xpm"
+#include "xpm/send20.xpm"
irc.cpp
@@ -4,10 +4,7 @@
 
 #include "headers.h"
 
-
-map<vector<unsigned char>, CAddress> mapIRCAddresses;
-CCriticalSection cs_mapIRCAddresses;
-
+int nGotIRCAddresses = 0;
 
 
 
@@ -259,16 +256,7 @@ void ThreadIRCSeed(void* parg)
                     CAddrDB addrdb;
                     if (AddAddress(addrdb, addr))
                         printf("IRC got new address\n");
-                    else
-                    {
-                        // make it try connecting again
-                        CRITICAL_BLOCK(cs_mapAddresses)
-                            if (mapAddresses.count(addr.GetKey()))
-                                mapAddresses[addr.GetKey()].nLastFailed = 0;
-                    }
-
-                    CRITICAL_BLOCK(cs_mapIRCAddresses)
-                        mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
+                    nGotIRCAddresses++;
                 }
                 else
                 {
irc.h
@@ -4,7 +4,5 @@
 
 extern bool RecvLine(SOCKET hSocket, string& strLine);
 extern void ThreadIRCSeed(void* parg);
-extern bool fRestartIRCSeed;
 
-extern map<vector<unsigned char>, CAddress> mapIRCAddresses;
-extern CCriticalSection cs_mapIRCAddresses;
+extern int nGotIRCAddresses;
main.cpp
@@ -100,13 +100,10 @@ bool AddToWallet(const CWalletTx& wtxIn)
         if (fInsertedNew)
             wtx.nTimeReceived = GetAdjustedTime();
 
-        //// debug print
-        printf("AddToWallet %s  %s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), fInsertedNew ? "new" : "update");
-
+        bool fUpdated = false;
         if (!fInsertedNew)
         {
             // Merge
-            bool fUpdated = false;
             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
             {
                 wtx.hashBlock = wtxIn.hashBlock;
@@ -128,13 +125,15 @@ bool AddToWallet(const CWalletTx& wtxIn)
                 wtx.fSpent = wtxIn.fSpent;
                 fUpdated = true;
             }
-            if (!fUpdated)
-                return true;
         }
 
+        //// debug print
+        printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,6).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+
         // Write to disk
-        if (!wtx.WriteToDisk())
-            return false;
+        if (fInsertedNew || fUpdated)
+            if (!wtx.WriteToDisk())
+                return false;
 
         // Notify UI
         vWalletUpdated.push_back(hash);
@@ -820,7 +819,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
             }
 
             if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
-                return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size());
+                return error("ConnectInputs() : %s prevout.n out of range %d %d %d prev tx %s\n%s", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,6).c_str(), txPrev.ToString().c_str());
 
             // If prev is coinbase, check that it's matured
             if (txPrev.IsCoinBase())
@@ -1217,7 +1216,7 @@ bool CBlock::AcceptBlock()
     if (nTime <= pindexPrev->GetMedianTimePast())
         return error("AcceptBlock() : block's timestamp is too early");
 
-    // Check that all transactions are finalized (starting around 30 Nov 2009)
+    // Check that all transactions are finalized (starting around Dec 2009)
     if (nBestHeight > 31000) // 25620 + 5320
         foreach(const CTransaction& tx, vtx)
             if (!tx.IsFinal(nTime))
@@ -1384,7 +1383,7 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM
 {
     if (nFile == -1)
         return NULL;
-    FILE* file = fopen(strprintf("%s\\blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
+    FILE* file = fopen(strprintf("%s/blk%04d.dat", GetDataDir().c_str(), nFile).c_str(), pszMode);
     if (!file)
         return NULL;
     if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w'))
@@ -1718,6 +1717,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 
 
 
+
     if (strCommand == "version")
     {
         // Each connection can only send one version message
@@ -1765,6 +1765,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 
         pfrom->fSuccessfullyConnected = true;
 
+        // Update the last seen time
+        if (pfrom->fNetworkNode)
+            AddressCurrentlyConnected(pfrom->addr);
+
         printf("version message: version %d\n", pfrom->nVersion);
     }
 
@@ -1781,23 +1785,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vector<CAddress> vAddr;
         vRecv >> vAddr;
 
-        // Clear addrknown lists periodically to allow refresh broadcasts
-        static int64 nLastClearedAddrKnown;
-        if (nLastClearedAddrKnown < GetAdjustedTime() - 24 * 60 * 60)
-        {
-            nLastClearedAddrKnown = GetAdjustedTime();
-            CRITICAL_BLOCK(cs_vNodes)
-                foreach(CNode* pnode, vNodes)
-                    pnode->setAddrKnown.clear();
-        }
-
         // Store the new addresses
         CAddrDB addrdb;
-        foreach(const CAddress& addr, vAddr)
+        foreach(CAddress& addr, vAddr)
         {
             if (fShutdown)
                 return true;
-            AddAddress(addrdb, addr);
+            addr.nTime = GetAdjustedTime();
+            if (pfrom->fGetAddr)
+                addr.nTime -= 5 * 24 * 60 * 60;
+            AddAddress(addrdb, addr, false);
             pfrom->AddAddressKnown(addr);
             if (!pfrom->fGetAddr && addr.IsRoutable())
             {
@@ -1816,6 +1813,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vector<CInv> vInv;
         vRecv >> vInv;
 
+        // Update the last seen time for this node's address
+        if (pfrom->fNetworkNode)
+            AddressCurrentlyConnected(pfrom->addr);
+
         CTxDB txdb("r");
         foreach(const CInv& inv, vInv)
         {
@@ -2099,6 +2100,25 @@ bool SendMessages(CNode* pto)
         if (pto->nVersion == 0)
             return true;
 
+        // Address refresh broadcast
+        static int64 nLastRebroadcast;
+        if (nLastRebroadcast < GetTime() - 24 * 60 * 60) // every 24 hours
+        {
+            nLastRebroadcast = GetTime();
+            CRITICAL_BLOCK(cs_vNodes)
+            {
+                foreach(CNode* pnode, vNodes)
+                {
+                    // Periodically clear setAddrKnown to allow refresh broadcasts
+                    pnode->setAddrKnown.clear();
+
+                    // Rebroadcast our address
+                    if (addrLocalHost.IsRoutable() && !fUseProxy)
+                        pnode->PushAddress(addrLocalHost);
+                }
+            }
+        }
+
 
         //
         // Message: addr
@@ -2187,7 +2207,7 @@ void GenerateBitcoins(bool fGenerate)
     }
     if (fGenerateBitcoins)
     {
-        int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+        int nProcessors = wxThread::GetCPUCount();
         printf("%d processors\n", nProcessors);
         if (nProcessors < 1)
             nProcessors = 1;
main.h
@@ -968,6 +968,14 @@ public:
             return error("CBlock::WriteToDisk() : ftell failed");
         fileout << *this;
 
+        // Flush stdio buffers and commit to disk before returning
+        fflush(fileout);
+#ifdef __WXMSW__
+        _commit(_fileno(fileout));
+#else
+        fsync(fileno(fileout));
+#endif
+
         return true;
     }
 
makefile.unix
@@ -0,0 +1,86 @@
+# Copyright (c) 2009 Satoshi Nakamoto
+# Distributed under the MIT/X11 software license, see the accompanying
+# file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+
+ifneq "$(BUILD)" "debug"
+ifneq "$(BUILD)" "release"
+BUILD=debug
+endif
+endif
+ifeq "$(BUILD)" "debug"
+D=d
+DEBUGFLAGS=-g -D__WXDEBUG__
+endif
+
+
+
+INCLUDEPATHS=-I"/usr/include" \
+             -I"/usr/local/boost_1_40_0" \
+             -I"/usr/local/db-4.7.25.NC/build_unix" \
+             -I"/usr/local/include/wx-2.8" \
+             -I"/usr/local/lib/wx/include/gtk2-ansi-debug-static-2.8"
+
+LIBPATHS=-L"/usr/lib" \
+         -L"/usr/local/lib" \
+         -L"/usr/local/db-4.7.25.NC/build_unix"
+
+LIBS= \
+ -Wl,-Bstatic -l boost_thread -l boost_system -l boost_filesystem -Wl,-Bdynamic \
+ -Wl,-Bstatic -l db_cxx -l wx_gtk2$(D)-2.8 -Wl,-Bdynamic \
+ -l crypto \
+ -l gtk-x11-2.0 -l gthread-2.0 -l SM
+WXDEFS=-D__WXGTK__ -DNOPCH
+CFLAGS=-O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
+HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
+
+
+
+all: bitcoin
+
+
+headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/util.o: util.cpp		    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/script.o: script.cpp	    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/db.o: db.cpp		    $(HEADERS) market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/net.o: net.cpp		    $(HEADERS) net.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/main.o: main.cpp		    $(HEADERS) net.h market.h sha.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/market.o: market.cpp	    $(HEADERS) market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/ui.o: ui.cpp		    $(HEADERS) net.h uibase.h ui.h market.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/uibase.o: uibase.cpp	    uibase.h
+	g++ -c $(CFLAGS) -o $@ $<
+
+obj/sha.o: sha.cpp		    sha.h
+	g++ -c $(CFLAGS) -O3 -o $@ $<
+
+obj/irc.o:  irc.cpp		    $(HEADERS)
+	g++ -c $(CFLAGS) -o $@ $<
+
+
+
+
+OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
+	obj/ui.o obj/uibase.o obj/sha.o obj/irc.o 
+
+bitcoin: headers.h.gch $(OBJS)
+	g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
+
+clean:
+	-rm obj/*
+	-rm headers.h.gch
net.cpp
@@ -3,7 +3,6 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
-#include <winsock2.h>
 
 void ThreadMessageHandler2(void* parg);
 void ThreadSocketHandler2(void* parg);
@@ -201,12 +200,14 @@ bool GetMyExternalIP(unsigned int& ipRet)
 
 
 
-bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
+bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
 {
     if (!addr.IsRoutable())
         return false;
     if (addr.ip == addrLocalHost.ip)
         return false;
+    if (fCurrentlyOnline)
+        addr.nTime = GetAdjustedTime();
     CRITICAL_BLOCK(cs_mapAddresses)
     {
         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
@@ -219,24 +220,47 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
         }
         else
         {
+            bool fUpdated = false;
             CAddress& addrFound = (*it).second;
             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
             {
                 // Services have been added
                 addrFound.nServices |= addr.nServices;
-                addrdb.WriteAddress(addrFound);
-                return true;
+                fUpdated = true;
+            }
+            int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
+            if (addrFound.nTime < addr.nTime - nUpdateInterval)
+            {
+                // Periodically update most recently seen time
+                addrFound.nTime = addr.nTime;
+                fUpdated = true;
             }
-            else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60)
+            if (fUpdated)
+                addrdb.WriteAddress(addrFound);
+        }
+    }
+    return false;
+}
+
+void AddressCurrentlyConnected(const CAddress& addr)
+{
+    CRITICAL_BLOCK(cs_mapAddresses)
+    {
+        // Only if it's been published already
+        map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
+        if (it != mapAddresses.end())
+        {
+            CAddress& addrFound = (*it).second;
+            int64 nUpdateInterval = 60 * 60;
+            if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
             {
                 // Periodically update most recently seen time
                 addrFound.nTime = GetAdjustedTime();
+                CAddrDB addrdb;
                 addrdb.WriteAddress(addrFound);
-                return false;
             }
         }
     }
-    return false;
 }
 
 
@@ -398,9 +422,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
         printf("connected %s\n", addrConnect.ToStringLog().c_str());
 
         // Set to nonblocking
-        u_long nOne = 1;
+#ifdef __WXMSW__
+		u_long nOne = 1;
         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
+#else
+        if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
+            printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
+#endif
 
         // Add node
         CNode* pnode = new CNode(hSocket, addrConnect, false);
@@ -418,7 +447,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
     else
     {
         CRITICAL_BLOCK(cs_mapAddresses)
-            mapAddresses[addrConnect.GetKey()].nLastFailed = GetTime();
+            mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();
         return NULL;
     }
 }
@@ -432,7 +461,7 @@ void CNode::DoDisconnect()
     // If outbound and never got version message, mark address as failed
     if (!fInbound && !fSuccessfullyConnected)
         CRITICAL_BLOCK(cs_mapAddresses)
-            mapAddresses[addr.GetKey()].nLastFailed = GetTime();
+            mapAddresses[addr.GetKey()].nLastFailed = GetAdjustedTime();
 
     // All of a nodes broadcasts and subscriptions are automatically torn down
     // when it goes down, so a node has to stay up to keep its broadcast going.
@@ -549,8 +578,8 @@ void ThreadSocketHandler2(void* parg)
         timeout.tv_sec  = 0;
         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
 
-        struct fd_set fdsetRecv;
-        struct fd_set fdsetSend;
+        fd_set fdsetRecv;
+        fd_set fdsetSend;
         FD_ZERO(&fdsetRecv);
         FD_ZERO(&fdsetSend);
         SOCKET hSocketMax = 0;
@@ -599,7 +628,11 @@ void ThreadSocketHandler2(void* parg)
         if (FD_ISSET(hListenSocket, &fdsetRecv))
         {
             struct sockaddr_in sockaddr;
+#ifdef __WXMSW__
             int len = sizeof(sockaddr);
+#else
+            socklen_t len = sizeof(sockaddr);
+#endif
             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
             CAddress addr(sockaddr);
             if (hSocket == INVALID_SOCKET)
@@ -765,14 +798,12 @@ void ThreadOpenConnections2(void* parg)
     }
 
     // Initiate network connections
-    int nTry = 0;
-    bool fIRCOnly = false;
-    const int nMaxConnections = 15;
     loop
     {
         // Wait
         vnThreadsRunning[1]--;
         Sleep(500);
+        const int nMaxConnections = 15;
         while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
         {
             CheckForShutdown(1);
@@ -781,93 +812,55 @@ void ThreadOpenConnections2(void* parg)
         vnThreadsRunning[1]++;
         CheckForShutdown(1);
 
-
         //
-        // The IP selection process is designed to limit vulnerability to address flooding.
-        // Any class C (a.b.c.?) has an equal chance of being chosen, then an IP is
-        // chosen within the class C.  An attacker may be able to allocate many IPs, but
-        // they would normally be concentrated in blocks of class C's.  They can hog the
-        // attention within their class C, but not the whole IP address space overall.
-        // A lone node in a class C will get as much attention as someone holding all 255
-        // IPs in another class C.
+        // Choose an address to connect to based on most recently seen
         //
+        CAddress addrConnect;
+        int64 nBestTime = 0;
+        int64 nDelay = ((60 * 60) << vNodes.size());
+        if (vNodes.size() >= 3)
+            nDelay *= 4;
+        if (nGotIRCAddresses > 0)
+            nDelay *= 100;
+
+        // Do this here so we don't have to critsect vNodes inside mapAddresses critsect
+        set<unsigned int> setConnected;
+        CRITICAL_BLOCK(cs_vNodes)
+            foreach(CNode* pnode, vNodes)
+                setConnected.insert(pnode->addr.ip);
 
-        // Every other try is with IRC addresses only
-        fIRCOnly = !fIRCOnly;
-        if (mapIRCAddresses.empty())
-            fIRCOnly = false;
-        else if (nTry++ < 30 && vNodes.size() < nMaxConnections/2)
-            fIRCOnly = true;
-
-        // Make a list of unique class C's
-        unsigned char pchIPCMask[4] = { 0xff, 0xff, 0xff, 0x00 };
-        unsigned int nIPCMask = *(unsigned int*)pchIPCMask;
-        vector<unsigned int> vIPC;
-        CRITICAL_BLOCK(cs_mapIRCAddresses)
         CRITICAL_BLOCK(cs_mapAddresses)
         {
-            vIPC.reserve(mapAddresses.size());
-            unsigned int nPrev = 0;
             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
             {
                 const CAddress& addr = item.second;
-                if (!addr.IsIPv4())
-                    continue;
-                if (fIRCOnly && !mapIRCAddresses.count(item.first))
+                if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
                     continue;
 
-                // Taking advantage of mapAddresses being in sorted order,
-                // with IPs of the same class C grouped together.
-                unsigned int ipC = addr.ip & nIPCMask;
-                if (ipC != nPrev)
-                    vIPC.push_back(nPrev = ipC);
-            }
-        }
-        if (vIPC.empty())
-            continue;
-
-        // Choose a random class C
-        unsigned int ipC = vIPC[GetRand(vIPC.size())];
+                // Limit retry frequency
+                if (GetAdjustedTime() < addr.nLastFailed + nDelay)
+                    continue;
 
-        // Organize all addresses in the class C by IP
-        map<unsigned int, vector<CAddress> > mapIP;
-        CRITICAL_BLOCK(cs_mapIRCAddresses)
-        CRITICAL_BLOCK(cs_mapAddresses)
-        {
-            int64 nDelay = ((30 * 60) << vNodes.size());
-            if (!fIRCOnly)
-            {
-                nDelay *= 2;
-                if (vNodes.size() >= 3)
-                    nDelay *= 4;
-                if (!mapIRCAddresses.empty())
-                    nDelay *= 100;
-            }
+                // Try again only after all addresses had a first attempt
+                int64 nTime = addr.nTime;
+                if (addr.nLastFailed > addr.nTime)
+                    nTime -= 365 * 24 * 60 * 60;
 
-            for (map<vector<unsigned char>, CAddress>::iterator mi = mapAddresses.lower_bound(CAddress(ipC, 0).GetKey());
-                 mi != mapAddresses.upper_bound(CAddress(ipC | ~nIPCMask, 0xffff).GetKey());
-                 ++mi)
-            {
-                const CAddress& addr = (*mi).second;
-                if (fIRCOnly && !mapIRCAddresses.count((*mi).first))
-                    continue;
+                // Randomize the order a little, putting the standard port first
+                nTime += GetRand(1 * 60 * 60);
+                if (addr.port != DEFAULT_PORT)
+                    nTime -= 1 * 60 * 60;
 
-                int64 nRandomizer = (addr.nLastFailed * addr.ip * 7777U) % 20000;
-                if (GetTime() - addr.nLastFailed > nDelay * nRandomizer / 10000)
-                    mapIP[addr.ip].push_back(addr);
+                if (nTime > nBestTime)
+                {
+                    nBestTime = nTime;
+                    addrConnect = addr;
+                }
             }
         }
-        if (mapIP.empty())
-            continue;
-
-        // Choose a random IP in the class C
-        map<unsigned int, vector<CAddress> >::iterator mi = mapIP.begin();
-        advance(mi, GetRand(mapIP.size()));
 
-        // Once we've chosen an IP, we'll try every given port before moving on
-        foreach(const CAddress& addrConnect, (*mi).second)
-            if (OpenNetworkConnection(addrConnect))
-                break;
+        if (addrConnect.IsValid())
+            OpenNetworkConnection(addrConnect);
     }
 }
 
@@ -989,6 +982,7 @@ bool StartNode(string& strError)
         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
     strError = "";
 
+#ifdef __WXMSW__
     // Sockets startup
     WSADATA wsadata;
     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
@@ -998,6 +992,7 @@ bool StartNode(string& strError)
         printf("%s\n", strError.c_str());
         return false;
     }
+#endif
 
     // Get local host ip
     char pszHostName[255];
@@ -1029,10 +1024,14 @@ bool StartNode(string& strError)
     }
 
     // Set to nonblocking, incoming connections will also inherit this
+#ifdef __WXMSW__
     u_long nOne = 1;
     if (ioctlsocket(hListenSocket, FIONBIO, &nOne) == SOCKET_ERROR)
net.h
@@ -22,7 +22,8 @@ enum
 
 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
 bool GetMyExternalIP(unsigned int& ipRet);
-bool AddAddress(CAddrDB& addrdb, const CAddress& addr);
+bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline=true);
+void AddressCurrentlyConnected(const CAddress& addr);
 CNode* FindNode(unsigned int ip);
 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
ui.cpp
@@ -260,7 +260,8 @@ void AddPendingReplyEvent3(void* pevthandler, CDataStream& vRecv)
 CDataStream GetStreamFromEvent(const wxCommandEvent& event)
 {
     wxString strData = event.GetString();
-    return CDataStream(strData.begin(), strData.begin() + event.GetInt(), SER_NETWORK);
+    const char* pszBegin = strData.c_str();
+    return CDataStream(pszBegin, pszBegin + event.GetInt(), SER_NETWORK);
 }
 
 
@@ -288,20 +289,6 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     SetIcon(wxICON(bitcoin));
     ptaskbaricon = new CMyTaskBarIcon();
 
-    // Init toolbar with transparency masked bitmaps
-    m_toolBar->ClearTools();
-
-    //// shouldn't have to do mask separately anymore, bitmap alpha support added in wx 2.8.9,
-    wxBitmap bmpSend(wxT("send20"), wxBITMAP_TYPE_RESOURCE);
-    bmpSend.SetMask(new wxMask(wxBitmap(wxT("send20mask"), wxBITMAP_TYPE_RESOURCE)));
-    m_toolBar->AddTool(wxID_BUTTONSEND, wxT("&Send Coins"), bmpSend, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
-
-    wxBitmap bmpAddressBook(wxT("addressbook20"), wxBITMAP_TYPE_RESOURCE);
-    bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook20mask"), wxBITMAP_TYPE_RESOURCE)));
-    m_toolBar->AddTool(wxID_BUTTONRECEIVE, wxT("&Address Book"), bmpAddressBook, wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString);
-
-    m_toolBar->Realize();
-
     // Init column headers
     int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8;
     if (!strstr(DateTimeStr(1229413914).c_str(), "2008"))
@@ -909,15 +896,17 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
         {
             TRY_CRITICAL_BLOCK(cs_mapWallet)
             {
-                bool fInserted = false;
+                string strTop;
+                if (m_listCtrl->GetItemCount())
+                    strTop = (string)m_listCtrl->GetItemText(0);
                 foreach(uint256 hash, vWalletUpdated)
                 {
                     map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
                     if (mi != mapWallet.end())
-                        fInserted |= InsertTransaction((*mi).second, false);
+                        InsertTransaction((*mi).second, false);
                 }
                 vWalletUpdated.clear();
-                if (fInserted)
+                if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
                     m_listCtrl->ScrollList(0, INT_MAX);
             }
         }
@@ -954,7 +943,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     string strStatus = strprintf("     %d connections     %d blocks     %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
     m_statusBar->SetStatusText(strStatus, 2);
 
+#ifdef __WXMSW__
     m_listCtrl->OnPaint(event);
+#endif
 }
 
 
@@ -1407,7 +1398,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
     m_checkBoxLimitProcessors->SetValue(fLimitProcessors);
     m_spinCtrlLimitProcessors->Enable(fLimitProcessors);
     m_spinCtrlLimitProcessors->SetValue(nLimitProcessors);
-    int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+    int nProcessors = wxThread::GetCPUCount();
     if (nProcessors < 1)
         nProcessors = 999;
     m_spinCtrlLimitProcessors->SetRange(1, nProcessors);
@@ -1549,17 +1540,11 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
         walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
     }
 
-    if (fUseProxy != m_checkBoxUseProxy->GetValue())
-    {
-        fUseProxy = m_checkBoxUseProxy->GetValue();
-        walletdb.WriteSetting("fUseProxy", fUseProxy);
-    }
+    fUseProxy = m_checkBoxUseProxy->GetValue();
+    walletdb.WriteSetting("fUseProxy", fUseProxy);
 
-    if (addrProxy != GetProxyAddr())
-    {
-        addrProxy = GetProxyAddr();
-        walletdb.WriteSetting("addrProxy", addrProxy);
-    }
+    addrProxy = GetProxyAddr();
+    walletdb.WriteSetting("addrProxy", addrProxy);
 }
 
 
@@ -1608,10 +1593,8 @@ CSendDialog::CSendDialog(wxWindow* parent, const wxString& strAddress) : CSendDi
     //// todo: should add a display of your balance for convenience
 
     // Set Icon
-    wxBitmap bmpSend(wxT("send16"), wxBITMAP_TYPE_RESOURCE);
-    bmpSend.SetMask(new wxMask(wxBitmap(wxT("send16masknoshadow"), wxBITMAP_TYPE_RESOURCE)));
     wxIcon iconSend;
-    iconSend.CopyFromBitmap(bmpSend);
+    iconSend.CopyFromBitmap(wxBitmap(send16noshadow_xpm));
     SetIcon(iconSend);
 
     wxCommandEvent event;
@@ -2231,10 +2214,8 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
     m_listCtrl->SetFocus();
 
     // Set Icon
-    wxBitmap bmpAddressBook(wxT("addressbook16"), wxBITMAP_TYPE_RESOURCE);
-    bmpAddressBook.SetMask(new wxMask(wxBitmap(wxT("addressbook16mask"), wxBITMAP_TYPE_RESOURCE)));
     wxIcon iconAddressBook;
-    iconAddressBook.CopyFromBitmap(bmpAddressBook);
+    iconAddressBook.CopyFromBitmap(wxBitmap(addressbook16_xpm));
     SetIcon(iconAddressBook);
 
     // Fill listctrl with address book data
@@ -3345,7 +3326,7 @@ bool CMyApp::OnInit2()
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
 #endif
-#ifdef __WXDEBUG__
+#if defined(__WXMSW__) && defined(__WXDEBUG__)
     // Disable malfunctioning wxWidgets debug assertion
     g_isPainting = 10000;
 #endif
@@ -3362,8 +3343,7 @@ bool CMyApp::OnInit2()
             "  -gen=0\t\t  Don't generate coins\n"
             "  -min\t\t  Start minimized\n"
             "  -datadir=<dir>\t  Specify data directory\n"
-            "  -proxy=<ip:port>\t  Connect through socks4 proxy,\n"
-            "  \t\t     e.g. -proxy=127.0.0.1:9050 to use TOR\n"
+            "  -proxy=<ip:port>\t  Connect through socks4 proxy\n"
             "  -addnode=<ip>\t  Add a node to connect to\n"
             "  -connect=<ip>\t  Connect only to the specified node\n"
             "  -?\t\t  This help message\n";
@@ -3386,6 +3366,8 @@ bool CMyApp::OnInit2()
         unsigned int nStart = GetTime();
         loop
         {
+            // TODO: find out how to do this in Linux, or replace with wxWidgets commands
+#ifdef __WXMSW__
             // Show the previous instance and exit
             HWND hwndPrev = FindWindow("wxWindowClassNR", "Bitcoin");
             if (hwndPrev)
@@ -3395,6 +3377,7 @@ bool CMyApp::OnInit2()
                 SetForegroundWindow(hwndPrev);
                 return false;
             }
+#endif
 
             if (GetTime() > nStart + 60)
                 return false;
@@ -3421,7 +3404,7 @@ bool CMyApp::OnInit2()
         fPrintToDebugger = true;
 
     printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
-    printf("Bitcoin version %d, Windows version %08x\n", VERSION, GetVersion());
+    printf("Bitcoin version %d, OS version %s\n", VERSION, wxGetOsDescription().mb_str());
 
     if (mapArgs.count("-dropmessages"))
     {
@@ -3493,12 +3476,36 @@ bool CMyApp::OnInit2()
         return false;
     }
 
+    if (mapArgs.count("-printblock"))
+    {
+        string strMatch = mapArgs["-printblock"];
+        int nFound = 0;
+        for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
+        {
+            uint256 hash = (*mi).first;
+            if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
+            {
+                CBlockIndex* pindex = (*mi).second;
+                CBlock block;
+                block.ReadFromDisk(pindex, true);
+                block.BuildMerkleTree();
+                block.print();
+                printf("\n");
+                nFound++;
+            }
+        }
+        if (nFound == 0)
+            printf("No blocks matching %s were found\n", strMatch.c_str());
+        OnExit();
+        return false;
+    }
+
     if (mapArgs.count("-gen"))
     {
         if (mapArgs["-gen"].empty())
             fGenerateBitcoins = true;
         else
-            fGenerateBitcoins = atoi(mapArgs["-gen"].c_str());
+            fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
     }
 
     if (mapArgs.count("-proxy"))
@@ -3511,9 +3518,6 @@ bool CMyApp::OnInit2()
             OnExit();
             return false;
         }
-        CWalletDB walletdb;
-        walletdb.WriteSetting("fUseProxy", fUseProxy);
-        walletdb.WriteSetting("addrProxy", addrProxy);
     }
 
     if (mapArgs.count("-addnode"))
@@ -3522,6 +3526,7 @@ bool CMyApp::OnInit2()
         foreach(string strAddr, mapMultiArgs["-addnode"])
         {
             CAddress addr(strAddr, NODE_NETWORK);
+            addr.nTime = 0; // so it won't relay unless successfully connected
             if (addr.IsValid())
                 AddAddress(addrdb, addr);
         }
@@ -3559,7 +3564,11 @@ bool CMyApp::OnInit2()
     //
     // Tests
     //
+#ifdef __WXMSW__
     if (argc >= 2 && stricmp(argv[1], "-send") == 0)
+#else
+    if (argc >= 2 && strcmp(argv[1], "-send") == 0)
+#endif
     {
         int64 nValue = 1;
         if (argc >= 3)
@@ -3646,7 +3655,8 @@ void CMyApp::OnFatalException()
 
 
 
-typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+#ifdef __WXMSW__
+typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
 
 string MyGetSpecialFolderPath(int nFolder, bool fCreate)
 {
@@ -3737,7 +3747,10 @@ void SetStartOnSystemStartup(bool fAutoStart)
         CoUninitialize();
     }
 }
-
+#else
+bool GetStartOnSystemStartup() { return false; }
+void SetStartOnSystemStartup(bool fAutoStart) { }
+#endif
 
 
 
uibase.cpp
@@ -7,6 +7,10 @@
 
 #include "uibase.h"
 
+#include "xpm/addressbook20.xpm"
+#include "xpm/check.xpm"
+#include "xpm/send20.xpm"
+
 ///////////////////////////////////////////////////////////////////////////
 
 CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
@@ -60,8 +64,8 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
 	m_toolBar->SetToolSeparation( 1 );
 	m_toolBar->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
 	
-	m_toolBar->AddTool( wxID_BUTTONSEND, wxT("&Send Coins"), wxBitmap( wxT("send20"), wxBITMAP_TYPE_RESOURCE ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
-	m_toolBar->AddTool( wxID_BUTTONRECEIVE, wxT("&Address Book"), wxBitmap( wxT("addressbook20"), wxBITMAP_TYPE_RESOURCE ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
+	m_toolBar->AddTool( wxID_BUTTONSEND, wxT("&Send Coins"), wxBitmap( send20_xpm ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
+	m_toolBar->AddTool( wxID_BUTTONRECEIVE, wxT("&Address Book"), wxBitmap( addressbook20_xpm ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString );
 	m_toolBar->Realize();
 	
 	m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY );
@@ -666,7 +670,7 @@ CSendDialogBase::CSendDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
 	
 	bSizer47->Add( 0, 0, 1, wxEXPAND, 5 );
 	
-	m_bitmapCheckMark = new wxStaticBitmap( this, wxID_ANY, wxICON( check ), wxDefaultPosition, wxSize( 16,16 ), 0 );
+	m_bitmapCheckMark = new wxStaticBitmap( this, wxID_ANY, wxBitmap( check_xpm ), wxDefaultPosition, wxSize( 16,16 ), 0 );
 	bSizer47->Add( m_bitmapCheckMark, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
 	
 	m_staticText36 = new wxStaticText( this, wxID_ANY, wxT("Pay &To:"), wxDefaultPosition, wxSize( -1,-1 ), wxALIGN_RIGHT );
uiproject.fbp
@@ -225,7 +225,7 @@
                     </object>
                 </object>
             </object>
-            <object class="wxToolBar" expanded="0">
+            <object class="wxToolBar" expanded="1">
                 <property name="bg"></property>
                 <property name="bitmapsize">20,20</property>
                 <property name="context_help"></property>
@@ -273,7 +273,7 @@
                 <event name="OnSize"></event>
                 <event name="OnUpdateUI"></event>
                 <object class="tool" expanded="1">
-                    <property name="bitmap">send20; Load From Resource</property>
+                    <property name="bitmap">xpm/send20.xpm; Load From File</property>
                     <property name="id">wxID_BUTTONSEND</property>
                     <property name="kind">wxITEM_NORMAL</property>
                     <property name="label">&amp;Send Coins</property>
@@ -287,7 +287,7 @@
                     <event name="OnUpdateUI"></event>
                 </object>
                 <object class="tool" expanded="1">
-                    <property name="bitmap">addressbook20; Load From Resource</property>
+                    <property name="bitmap">xpm/addressbook20.xpm; Load From File</property>
                     <property name="id">wxID_BUTTONRECEIVE</property>
                     <property name="kind">wxITEM_NORMAL</property>
                     <property name="label">&amp;Address Book</property>
@@ -1685,7 +1685,7 @@
                 </object>
             </object>
         </object>
-        <object class="Dialog" expanded="1">
+        <object class="Dialog" expanded="0">
             <property name="bg"></property>
             <property name="center"></property>
             <property name="context_help"></property>
@@ -3699,7 +3699,7 @@
                                     <property name="proportion">0</property>
                                     <object class="wxStaticBitmap" expanded="1">
                                         <property name="bg"></property>
-                                        <property name="bitmap">check; Load From Icon Resource [-1; -1]</property>
+                                        <property name="bitmap">xpm/check.xpm; Load From File</property>
                                         <property name="context_help"></property>
                                         <property name="enabled">1</property>
                                         <property name="fg"></property>
util.cpp
@@ -38,8 +38,10 @@ public:
             ppmutexOpenSSL[i] = new wxMutex();
         CRYPTO_set_locking_callback(locking_callback);
 
+#ifdef __WXMSW__
         // Seed random number generator with screen scrape and other hardware sources
         RAND_screen();
+#endif
 
         // Seed random number generator with performance counter
         RandAddSeed();
@@ -325,8 +327,8 @@ void ParseParameters(int argc, char* argv[])
             pszValue = strchr(psz, '=');
             *pszValue++ = '\0';
         }
-        strlwr(psz);
         #ifdef __WXMSW__
+        _strlwr(psz);
         if (psz[0] == '/')
             psz[0] = '-';
         #endif
@@ -343,9 +345,13 @@ void ParseParameters(int argc, char* argv[])
 
 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
 {
+#ifdef __WXMSW__
     char pszModule[MAX_PATH];
     pszModule[0] = '\0';
     GetModuleFileName(NULL, pszModule, sizeof(pszModule));
+#else
+    const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
+#endif
     if (pex)
         snprintf(pszMessage, 1000,
             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
util.h
@@ -55,9 +55,34 @@ inline T& REF(const T& val)
 }
 
 #ifndef __WXMSW__
-#define closesocket(s)  close(s)
-#define INVALID_SOCKET  (SOCKET)(~0)
+#define _UI64_MAX           UINT64_MAX
+#define _I64_MAX            INT64_MAX
+#define WSAGetLastError()   errno
+#define WSAEWOULDBLOCK      EWOULDBLOCK
+#define WSAEMSGSIZE         EMSGSIZE
+#define WSAEINTR            EINTR
+#define WSAEINPROGRESS      EINPROGRESS
+#define WSAEADDRINUSE       EADDRINUSE
+#define closesocket(s)      close(s)
+#define INVALID_SOCKET      (SOCKET)(~0)
+#define SOCKET_ERROR        -1
 typedef u_int SOCKET;
+#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
+#define strlwr(psz)         to_lower(psz)
+#define _strlwr(psz)        to_lower(psz)
+#define _mkdir(psz)         filesystem::create_directory(psz)
+#define MAX_PATH            1024
+#define Sleep(n)            wxMilliSleep(n)
+#define Beep(n1,n2)         (0)
+inline int _beginthread(void(*pfn)(void*), unsigned nStack, void* parg) { thread(bind(pfn, parg)); return 0; }
+inline void _endthread() { pthread_exit(NULL); }
+inline int GetCurrentThread() { return 0; }
+// threads are processes on linux, so setpriority affects just the one thread
+inline void SetThreadPriority(int nThread, int nPriority) { setpriority(PRIO_PROCESS, getpid(), nPriority); }
+#define THREAD_PRIORITY_LOWEST          PRIO_MIN
+#define THREAD_PRIORITY_BELOW_NORMAL    2
+#define THREAD_PRIORITY_NORMAL          0
+#define THREAD_PRIORITY_ABOVE_NORMAL    0
 #endif
 
 
@@ -120,7 +145,7 @@ public:
 protected:
     wxMutex mutex;
 public:
-    explicit CCriticalSection() { }
+    explicit CCriticalSection() : mutex(wxMUTEX_RECURSIVE) { }
     ~CCriticalSection() { }
     void Enter() { mutex.Lock(); }
     void Leave() { mutex.Unlock(); }
@@ -183,7 +208,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
         // print to debug.log
         char pszFile[MAX_PATH+100];
         GetDataDir(pszFile);
-        strlcat(pszFile, "\\debug.log", sizeof(pszFile));
+        strlcat(pszFile, "/debug.log", sizeof(pszFile));
         FILE* fileout = fopen(pszFile, "a");
         if (fileout)
         {
@@ -354,13 +379,6 @@ inline int64 GetTimeMillis()
     return wxGetLocalTimeMillis().GetValue();
 }
 
-#ifndef __WXMSW__
-inline void Sleep(unsigned int nMilliseconds)
-{
-    wxMilliSleep(nMilliseconds);
-}
-#endif
-
 
 
 
xpm/addressbook16.xpm
@@ -0,0 +1,278 @@
+/* XPM */
+static char * addressbook16_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 256 2",
+"   c #FFFFFF",
+".  c #F7FFFF",
+"X  c #F7F7FF",
+"o  c #EFF7FF",
+"O  c #E6EFF7",
+"+  c #E6E6F7",
+"@  c #CEE6F7",
+"#  c #DEDEEF",
+"$  c #D6DEEF",
+"%  c #D6DEE6",
+"&  c #CEDEF7",
+"*  c #CEDEEF",
+"=  c #EFF708",
+"-  c #C5DEF7",
+";  c #CED6EF",
+":  c None",
+">  c #C5D6E6",
+",  c #BDD6F7",
+"<  c #BDD6EF",
+"1  c #D6CECE",
+"2  c #BDCEE6",
+"3  c #BDC5E6",
+"4  c #B5C5DE",
+"5  c #BDD631",
+"6  c #ADBDDE",
+"7  c #B5B5BD",
+"8  c #A5B5D6",
+"9  c #00FFFF",
+"0  c #9CB5CE",
+"q  c #9CADD6",
+"w  c #94A5D6",
+"e  c #8CA5D6",
+"r  c #8CA5CE",
+"t  c #8CA5C5",
+"y  c #849CC5",
+"u  c #7B9CD6",
+"i  c #7B9CCE",
+"p  c #31BDCE",
+"a  c #6B9CD6",
+"s  c #00F708",
+"d  c #8494AD",
+"f  c #7B94B5",
+"g  c #6B94D6",
+"h  c #6B9C84",
+"j  c #7B8CAD",
+"k  c #738CAD",
+"l  c #638CC5",
+"z  c #10CE42",
+"x  c #638CBD",
+"c  c #7B849C",
+"v  c #73849C",
+"b  c #6B84A5",
+"n  c #7B7BA5",
+"m  c #6B849C",
+"M  c #7B8C42",
+"N  c #5A84C5",
+"B  c #29AD6B",
+"V  c #F74A4A",
+"C  c #6384A5",
+"Z  c #5284C5",
+"A  c #637BA5",
+"S  c #637B9C",
+"D  c #9C637B",
+"F  c #6B7B5A",
+"G  c #637394",
+"H  c #52739C",
+"J  c #5A7384",
+"K  c #526B94",
+"L  c #426B94",
+"P  c #52638C",
+"I  c #426B7B",
+"U  c #5A5A8C",
+"Y  c #524A7B",
+"T  c #425273",
+"R  c #21636B",
+"E  c #106394",
+"W  c #106B52",
+"Q  c #3A4273",
+"!  c #31426B",
+"~  c #523163",
+"^  c #29426B",
+"/  c #293A63",
+"(  c #213A63",
+")  c #193A63",
+"_  c #193163",
+"`  c #19315A",
+"'  c #212963",
+"]  c #10315A",
+"[  c #082952",
+"{  c #FFCC33",
+"}  c #33FF33",
+"|  c #66FF33",
+" . c #99FF33",
+".. c #CCFF33",
+"X. c #FFFF33",
+"o. c #000066",
+"O. c #330066",
+"+. c #660066",
+"@. c #990066",
+"#. c #CC0066",
+"$. c #FF0066",
+"%. c #003366",
+"&. c #333366",
+"*. c #663366",
+"=. c #993366",
+"-. c #CC3366",
+";. c #FF3366",
+":. c #006666",
+">. c #336666",
+",. c #666666",
+"<. c #996666",
+"1. c #CC6666",
+"2. c #009966",
+"3. c #339966",
+"4. c #669966",
+"5. c #999966",
+"6. c #CC9966",
+"7. c #FF9966",
+"8. c #00CC66",
+"9. c #33CC66",
+"0. c #99CC66",
+"q. c #CCCC66",
+"w. c #FFCC66",
+"e. c #00FF66",
+"r. c #33FF66",
+"t. c #99FF66",
+"y. c #CCFF66",
+"u. c #FF00CC",
+"i. c #CC00FF",
+"p. c #009999",
+"a. c #993399",
+"s. c #990099",
+"d. c #CC0099",
+"f. c #000099",
+"g. c #333399",
+"h. c #660099",
+"j. c #CC3399",
+"k. c #FF0099",
+"l. c #006699",
+"z. c #336699",
+"x. c #663399",
+"c. c #996699",
+"v. c #CC6699",
+"b. c #FF3399",
+"n. c #339999",
+"m. c #669999",
+"M. c #999999",
+"N. c #CC9999",
+"B. c #FF9999",
+"V. c #00CC99",
+"C. c #33CC99",
+"Z. c #66CC66",
+"A. c #99CC99",
+"S. c #CCCC99",
+"D. c #FFCC99",
+"F. c #00FF99",
+"G. c #33FF99",
+"H. c #66CC99",
+"J. c #99FF99",
+"K. c #CCFF99",
+"L. c #FFFF99",
+"P. c #0000CC",
+"I. c #330099",
+"U. c #6600CC",
+"Y. c #9900CC",
+"T. c #CC00CC",
+"R. c #003399",
+"E. c #3333CC",
+"W. c #6633CC",
+"Q. c #9933CC",
+"!. c #CC33CC",
+"~. c #FF33CC",
+"^. c #0066CC",
+"/. c #3366CC",
+"(. c #666699",
+"). c #9966CC",
+"_. c #CC66CC",
+"`. c #FF6699",
+"'. c #0099CC",
+"]. c #3399CC",
+"[. c #6699CC",
+"{. c #9999CC",
xpm/addressbook20.xpm
xpm/bitcoin.xpm
xpm/check.xpm
xpm/send16.xpm
xpm/send16noshadow.xpm
xpm/send20.xpm