Add wallet privkey encryption.
[novacoin.git] / src / ui.cpp
index 6e28435..52315e1 100644 (file)
@@ -3,6 +3,11 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "db.h"
+#include "init.h"
+#include "strlcpy.h"
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/convenience.hpp>
 #ifdef _MSC_VER
 #include <crtdbg.h>
 #endif
@@ -18,6 +23,13 @@ CMyTaskBarIcon* ptaskbaricon = NULL;
 bool fClosedToTray = false;
 wxLocale g_locale;
 
+#ifdef __WXMSW__
+double nScaleX = 1.0;
+double nScaleY = 1.0;
+#else
+static const double nScaleX = 1.0;
+static const double nScaleY = 1.0;
+#endif
 
 
 
@@ -228,11 +240,46 @@ void SetDefaultReceivingAddress(const string& strAddress)
             return;
         if (!mapPubKeys.count(hash160))
             return;
-        CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
+        pwalletMain->SetDefaultKey(mapPubKeys[hash160]);
         pframeMain->m_textCtrlAddress->SetValue(strAddress);
     }
 }
 
+bool GetWalletPassphrase()
+{
+    if (pwalletMain->IsLocked())
+    {
+        string strWalletPass;
+        strWalletPass.reserve(100);
+        mlock(&strWalletPass[0], strWalletPass.capacity());
+
+        // obtain current wallet encrypt/decrypt key, from passphrase
+        // Note that the passphrase is not mlock()d during this entry and could potentially
+        // be obtained from disk long after bitcoin has run.
+        strWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
+                                              _("Passphrase")).ToStdString();
+
+        if (!strWalletPass.size())
+        {
+            fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+            munlock(&strWalletPass[0], strWalletPass.capacity());
+            wxMessageBox(_("Please supply the current wallet decryption passphrase."), "Bitcoin");
+            return false;
+        }
+
+        if (!pwalletMain->Unlock(strWalletPass))
+        {
+            fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+            munlock(&strWalletPass[0], strWalletPass.capacity());
+            wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin");
+            return false;
+        }
+        fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+        munlock(&strWalletPass[0], strWalletPass.capacity());
+    }
+    return true;
+}
+
 
 
 
@@ -263,9 +310,10 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     fOnSetFocusAddress = false;
     fRefresh = false;
     m_choiceFilter->SetSelection(0);
-    double dResize = 1.0;
+    double dResize = nScaleX;
 #ifdef __WXMSW__
     SetIcon(wxICON(bitcoin));
+    SetSize(dResize * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #else
     SetIcon(bitcoin80_xpm);
     SetBackgroundColour(m_toolBar->GetBackgroundColour());
@@ -277,7 +325,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     dResize = 1.22;
     SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
 #endif
-    m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+    m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
     m_listCtrl->SetFocus();
     ptaskbaricon = new CMyTaskBarIcon();
 #ifdef __WXMAC_OSX__
@@ -317,7 +365,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
 
     // Fill your address text box
     vector<unsigned char> vchPubKey;
-    if (CWalletDB("r").ReadDefaultKey(vchPubKey))
+    if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
         m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
 
     // Fill listctrl with wallet transactions
@@ -612,7 +660,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             {
                 int64 nUnmatured = 0;
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    nUnmatured += txout.GetCredit();
+                    nUnmatured += pwalletMain->GetCredit(txout);
                 if (wtx.IsInMainChain())
                 {
                     strDescription = strprintf(_("Generated (%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -648,19 +696,19 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 return false;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
             {
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                 {
                     vector<unsigned char> vchPubKey;
-                    if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                    if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                     {
-                        CRITICAL_BLOCK(cs_mapAddressBook)
+                        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
                         {
                             //strDescription += _("Received payment to ");
                             //strDescription += _("Received with address ");
                             strDescription += _("Received with: ");
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            map<string, string>::iterator mi = mapAddressBook.find(strAddress);
-                            if (mi != mapAddressBook.end() && !(*mi).second.empty())
+                            map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+                            if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
                             {
                                 string strLabel = (*mi).second;
                                 strDescription += strAddress.substr(0,12) + "... ";
@@ -690,11 +738,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
     {
         bool fAllFromMe = true;
         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-            fAllFromMe = fAllFromMe && txin.IsMine();
+            fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
         bool fAllToMe = true;
         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-            fAllToMe = fAllToMe && txout.IsMine();
+            fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
         if (fAllFromMe && fAllToMe)
         {
@@ -720,7 +768,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
             {
                 const CTxOut& txout = wtx.vout[nOut];
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                     continue;
 
                 string strAddress;
@@ -738,9 +786,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 }
 
                 string strDescription = _("To: ");
-                CRITICAL_BLOCK(cs_mapAddressBook)
-                    if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                        strDescription += mapAddressBook[strAddress] + " ";
+                CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+                    if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                        strDescription += pwalletMain->mapAddressBook[strAddress] + " ";
                 strDescription += strAddress;
                 if (!mapValue["message"].empty())
                 {
@@ -779,9 +827,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             //
             bool fAllMine = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllMine = fAllMine && txout.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txout);
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllMine = fAllMine && txin.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txin);
 
             InsertLine(fNew, nIndex, hash, strSort, colour,
                        strStatus,
@@ -808,16 +856,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         // Collect list of wallet transactions and sort newest first
         bool fEntered = false;
         vector<pair<unsigned int, uint256> > vSorted;
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             printf("RefreshListCtrl starting\n");
             fEntered = true;
             fRefreshListCtrl = false;
-            vWalletUpdated.clear();
+            pwalletMain->vWalletUpdated.clear();
 
             // Do the newest transactions first
-            vSorted.reserve(mapWallet.size());
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            vSorted.reserve(pwalletMain->mapWallet.size());
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 const CWalletTx& wtx = (*it).second;
                 unsigned int nTime = UINT_MAX - wtx.GetTxTime();
@@ -836,12 +884,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
             if (fShutdown)
                 return;
             bool fEntered = false;
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 fEntered = true;
                 uint256& hash = vSorted[i++].second;
-                map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                if (mi != mapWallet.end())
+                map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                if (mi != pwalletMain->mapWallet.end())
                     InsertTransaction((*mi).second, true);
             }
             if (!fEntered || i == 100 || i % 500 == 0)
@@ -859,10 +907,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         static int64 nLastTime;
         if (GetTime() > nLastTime + 30)
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 nLastTime = GetTime();
-                for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+                for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
                 {
                     CWalletTx& wtx = (*it).second;
                     if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime())
@@ -883,7 +931,7 @@ void CMainFrame::RefreshStatusColumn()
     if (nTop == nLastTop && pindexLastBest == pindexBest)
         return;
 
-    TRY_CRITICAL_BLOCK(cs_mapWallet)
+    TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         int nStart = nTop;
         int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
@@ -903,8 +951,8 @@ void CMainFrame::RefreshStatusColumn()
         for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
         {
             uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
-            map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-            if (mi == mapWallet.end())
+            map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+            if (mi == pwalletMain->mapWallet.end())
             {
                 printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n");
                 continue;
@@ -1001,41 +1049,41 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
         nLastRepaintTime = GetTimeMillis();
 
         // Update listctrl contents
-        if (!vWalletUpdated.empty())
+        if (!pwalletMain->vWalletUpdated.empty())
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 string strTop;
                 if (m_listCtrl->GetItemCount())
                     strTop = (string)m_listCtrl->GetItemText(0);
-                BOOST_FOREACH(uint256 hash, vWalletUpdated)
+                BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated)
                 {
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                    if (mi != pwalletMain->mapWallet.end())
                         InsertTransaction((*mi).second, false);
                 }
-                vWalletUpdated.clear();
+                pwalletMain->vWalletUpdated.clear();
                 if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
                     m_listCtrl->ScrollList(0, INT_MIN/2);
             }
         }
 
         // Balance total
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             fPaintedBalance = true;
-            m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+            m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
 
             // Count hidden and multi-line transactions
             nTransactionCount = 0;
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 CWalletTx& wtx = (*it).second;
                 nTransactionCount += wtx.nLinesDisplayed;
             }
         }
     }
-    if (!vWalletUpdated.empty() || !fPaintedBalance)
+    if (!pwalletMain->vWalletUpdated.empty() || !fPaintedBalance)
         nNeedRepaint++;
 
     // Update status column of visible items only
@@ -1061,7 +1109,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     m_statusBar->SetStatusText(strStatus, 2);
 
     // Update receiving address
-    string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
+    string strDefaultAddress = PubKeyToAddress(pwalletMain->vchDefaultKey);
     if (m_textCtrlAddress->GetValue() != strDefaultAddress)
         m_textCtrlAddress->SetValue(strDefaultAddress);
 }
@@ -1109,6 +1157,166 @@ void CMainFrame::OnMenuOptionsChangeYourAddress(wxCommandEvent& event)
         return;
 }
 
+void CMainFrame::OnMenuOptionsEncryptWallet(wxCommandEvent& event)
+{
+    // Options->Encrypt Wallet
+    if (pwalletMain->IsCrypted())
+    {
+        wxMessageBox(_("Wallet already encrypted."), "Bitcoin", wxOK | wxICON_ERROR);
+        return;
+    }
+
+    string strWalletPass;
+    strWalletPass.reserve(100);
+    mlock(&strWalletPass[0], strWalletPass.capacity());
+
+    // obtain current wallet encrypt/decrypt key, from passphrase
+    // Note that the passphrase is not mlock()d during this entry and could potentially
+    // be obtained from disk long after bitcoin has run.
+    strWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase to the wallet.\nPlease use a passphrase of 10 or more random characters, or eight or more words."),
+                                          _("Passphrase")).ToStdString();
+
+    if (!strWalletPass.size())
+    {
+        fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+        munlock(&strWalletPass[0], strWalletPass.capacity());
+        wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
+        return;
+    }
+
+    if(wxMessageBox(_("WARNING: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR BITCOINS!\nAre you sure you wish to encrypt your wallet?"), "Bitcoin", wxYES_NO) != wxYES)
+        return;
+
+    string strWalletPassTest;
+    strWalletPassTest.reserve(100);
+    mlock(&strWalletPassTest[0], strWalletPassTest.capacity());
+    strWalletPassTest = wxGetPasswordFromUser(_("Please re-enter your new wallet passphrase."),
+                                              _("Passphrase")).ToStdString();
+
+    if (strWalletPassTest != strWalletPass)
+    {
+        fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+        fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
+        munlock(&strWalletPass[0], strWalletPass.capacity());
+        munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
+        wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
+        return;
+    }
+
+    if (!pwalletMain->EncryptWallet(strWalletPass))
+    {
+        fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+        fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
+        munlock(&strWalletPass[0], strWalletPass.capacity());
+        munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
+        wxMessageBox(_("Wallet encryption failed."), "Bitcoin", wxOK | wxICON_ERROR);
+        return;
+    }
+    fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+    fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0');
+    munlock(&strWalletPass[0], strWalletPass.capacity());
+    munlock(&strWalletPassTest[0], strWalletPassTest.capacity());
+    wxMessageBox(_("Wallet Encrypted.\nRemember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."), "Bitcoin");
+}
+
+void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event)
+{
+    // Options->Change Wallet Encryption Passphrase
+    if (!pwalletMain->IsCrypted())
+    {
+        wxMessageBox(_("Wallet is unencrypted, please encrypt it first."), "Bitcoin", wxOK | wxICON_ERROR);
+        return;
+    }
+
+    string strOldWalletPass;
+    strOldWalletPass.reserve(100);
+    mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+
+    // obtain current wallet encrypt/decrypt key, from passphrase
+    // Note that the passphrase is not mlock()d during this entry and could potentially
+    // be obtained from disk long after bitcoin has run.
+    strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
+                                             _("Passphrase")).ToStdString();
+
+    CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
+    {
+        bool fWasLocked = pwalletMain->IsLocked();
+        pwalletMain->Lock();
+
+        if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
+        {
+            fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
+            munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+            wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
+            return;
+        }
+
+        if (fWasLocked)
+            pwalletMain->Lock();
+
+        string strNewWalletPass;
+        strNewWalletPass.reserve(100);
+        mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
+
+        // obtain new wallet encrypt/decrypt key, from passphrase
+        // Note that the passphrase is not mlock()d during this entry and could potentially
+        // be obtained from disk long after bitcoin has run.
+        strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
+                                                 _("Passphrase")).ToStdString();
+
+        if (!strNewWalletPass.size())
+        {
+            fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
+            fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
+            munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+            munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
+            wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
+            return;
+        }
+
+        string strNewWalletPassTest;
+        strNewWalletPassTest.reserve(100);
+        mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
+
+        // obtain new wallet encrypt/decrypt key, from passphrase
+        // Note that the passphrase is not mlock()d during this entry and could potentially
+        // be obtained from disk long after bitcoin has run.
+        strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
+                                                     _("Passphrase")).ToStdString();
+
+        if (strNewWalletPassTest != strNewWalletPass)
+        {
+            fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
+            fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
+            fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
+            munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+            munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
+            munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
+            wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
+            return;
+        }
+
+        if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
+        {
+            fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
+            fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
+            fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
+            munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+            munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
+            munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
+            wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
+            return;
+        }
+        fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
+        fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
+        fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
+        munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
+        munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
+        munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
+        wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
+    }
+}
+
 void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
 {
     // Options->Options
@@ -1169,11 +1377,23 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
         return;
     string strName = dialog.GetValue();
 
-    // Generate new key
-    string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+    string strAddress;
+    CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
+    {
+        bool fWasLocked = pwalletMain->IsLocked();
+        if (!GetWalletPassphrase())
+            return;
+
+        // Generate new key
+        strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
+
+        if (fWasLocked)
+            pwalletMain->Lock();
+    }
 
     // Save
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, strName);
     SetDefaultReceivingAddress(strAddress);
 }
 
@@ -1191,10 +1411,10 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
 {
     uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
     CWalletTx wtx;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-        if (mi == mapWallet.end())
+        map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+        if (mi == pwalletMain->mapWallet.end())
         {
             printf("CMainFrame::OnListItemActivated() : tx not found in mapWallet\n");
             return;
@@ -1219,7 +1439,10 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
 
 CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetailsDialogBase(parent)
 {
-    CRITICAL_BLOCK(cs_mapAddressBook)
+#ifdef __WXMSW__
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
+#endif
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strHTML;
         strHTML.reserve(4000);
@@ -1269,19 +1492,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Credit
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                     {
                         vector<unsigned char> vchPubKey;
-                        if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                        if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                         {
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            if (mapAddressBook.count(strAddress))
+                            if (pwalletMain->mapAddressBook.count(strAddress))
                             {
                                 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
                                 strHTML += _("<b>To:</b> ");
                                 strHTML += HtmlEscape(strAddress);
-                                if (!mapAddressBook[strAddress].empty())
-                                    strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
+                                if (!pwalletMain->mapAddressBook[strAddress].empty())
+                                    strHTML += _(" (yours, label: ") + pwalletMain->mapAddressBook[strAddress] + ")";
                                 else
                                     strHTML += _(" (yours)");
                                 strHTML += "<br>";
@@ -1303,8 +1526,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             // Online transaction
             strAddress = wtx.mapValue["to"];
             strHTML += _("<b>To:</b> ");
-            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                strHTML += mapAddressBook[strAddress] + " ";
+            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
             strHTML += HtmlEscape(strAddress) + "<br>";
         }
 
@@ -1319,7 +1542,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             //
             int64 nUnmatured = 0;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                nUnmatured += txout.GetCredit();
+                nUnmatured += pwalletMain->GetCredit(txout);
             strHTML += _("<b>Credit:</b> ");
             if (wtx.IsInMainChain())
                 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -1338,11 +1561,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             bool fAllFromMe = true;
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllFromMe = fAllFromMe && txin.IsMine();
+                fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
             bool fAllToMe = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllToMe = fAllToMe && txout.IsMine();
+                fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
             if (fAllFromMe)
             {
@@ -1351,7 +1574,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 //
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                         continue;
 
                     if (wtx.mapValue["to"].empty())
@@ -1362,8 +1585,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                         {
                             string strAddress = Hash160ToAddress(hash160);
                             strHTML += _("<b>To:</b> ");
-                            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                                strHTML += mapAddressBook[strAddress] + " ";
+                            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
                             strHTML += strAddress;
                             strHTML += "<br>";
                         }
@@ -1391,11 +1614,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Mixed debit transaction
                 //
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                    if (txin.IsMine())
-                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
+                    if (pwalletMain->IsMine(txin))
+                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    if (txout.IsMine())
-                        strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
+                    if (pwalletMain->IsMine(txout))
+                        strHTML += _("<b>Credit:</b> ") + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
             }
         }
 
@@ -1421,30 +1644,30 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             strHTML += "<hr><br>debug print<br><br>";
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                if (txin.IsMine())
-                    strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
+                if (pwalletMain->IsMine(txin))
+                    strHTML += "<b>Debit:</b> " + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                if (txout.IsMine())
-                    strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
+                if (pwalletMain->IsMine(txout))
+                    strHTML += "<b>Credit:</b> " + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
 
             strHTML += "<br><b>Transaction:</b><br>";
             strHTML += HtmlEscape(wtx.ToString(), true);
 
             strHTML += "<br><b>Inputs:</b><br>";
-            CRITICAL_BLOCK(cs_mapWallet)
+            CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
                 {
                     COutPoint prevout = txin.prevout;
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(prevout.hash);
+                    if (mi != pwalletMain->mapWallet.end())
                     {
                         const CWalletTx& prev = (*mi).second;
                         if (prevout.n < prev.vout.size())
                         {
                             strHTML += HtmlEscape(prev.ToString(), true);
                             strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", ";
-                            strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
+                            strHTML = strHTML + "IsMine=" + (pwalletMain->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "<br>";
                         }
                     }
                 }
@@ -1633,6 +1856,8 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
     SelectPage(0);
 #ifndef __WXMSW__
     SetSize(1.0 * GetSize().GetWidth(), 1.2 * GetSize().GetHeight());
+#else
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
 #if defined(__WXGTK__) || defined(__WXMAC_OSX__)
     m_checkBoxStartOnSystemStartup->SetLabel(_("&Start Bitcoin on window system startup"));
@@ -1733,7 +1958,7 @@ void COptionsDialog::OnButtonCancel(wxCommandEvent& event)
 
 void COptionsDialog::OnButtonApply(wxCommandEvent& event)
 {
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
 
     int64 nPrevTransactionFee = nTransactionFee;
     if (ParseMoney(m_textCtrlTransactionFee->GetValue(), nTransactionFee) && nTransactionFee != nPrevTransactionFee)
@@ -1803,6 +2028,8 @@ CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent)
         fontTmp.SetPointSize(8);
     m_staticTextMain->SetFont(fontTmp);
     SetSize(GetSize().GetWidth() + 44, GetSize().GetHeight() + 10);
+#else
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
 }
 
@@ -1837,12 +2064,21 @@ CSendDialog::CSendDialog(wxWindow* parent, const wxString& strAddress) : CSendDi
         fontTmp.SetPointSize(9);
     m_staticTextInstructions->SetFont(fontTmp);
     SetSize(725, 180);
+#else
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
     
     // Set Icon
-    wxIcon iconSend;
-    iconSend.CopyFromBitmap(wxBitmap(send16noshadow_xpm));
-    SetIcon(iconSend);
+    if (nScaleX == 1.0 && nScaleY == 1.0) // We don't have icons of the proper size otherwise
+    {
+        wxIcon iconSend;
+        iconSend.CopyFromBitmap(wxBitmap(send16noshadow_xpm));
+        SetIcon(iconSend);
+    }
+#ifdef __WXMSW__
+    else
+        SetIcon(wxICON(bitcoin));
+#endif
 
     // Fixup the tab order
     m_buttonPaste->MoveAfterInTabOrder(m_buttonCancel);
@@ -1899,12 +2135,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
             wxMessageBox(_("Error in amount  "), _("Send Coins"));
             return;
         }
-        if (nValue > GetBalance())
+        if (nValue > pwalletMain->GetBalance())
         {
             wxMessageBox(_("Amount exceeds your balance  "), _("Send Coins"));
             return;
         }
-        if (nValue + nTransactionFee > GetBalance())
+        if (nValue + nTransactionFee > pwalletMain->GetBalance())
         {
             wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included  "), _("Send Coins"));
             return;
@@ -1917,22 +2153,36 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
         if (fBitcoinAddress)
         {
            CRITICAL_BLOCK(cs_main)
+            CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
            {
+                bool fWasLocked = pwalletMain->IsLocked();
+                if (!GetWalletPassphrase())
+                    return;
+
                 // Send to bitcoin address
                 CScript scriptPubKey;
                 scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
 
-                string strError = SendMoney(scriptPubKey, nValue, wtx, true);
+                string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
                 if (strError == "")
                     wxMessageBox(_("Payment sent  "), _("Sending..."));
                 else if (strError == "ABORTED")
+                {
+                    if (fWasLocked)
+                        pwalletMain->Lock();
                     return; // leave send dialog open
+                }
                 else
                 {
                     wxMessageBox(strError + "  ", _("Sending..."));
                     EndModal(false);
+                    if (fWasLocked)
+                        pwalletMain->Lock();
                     return;
                 }
+
+                if (fWasLocked)
+                    pwalletMain->Lock();
            }
         }
         else
@@ -1954,9 +2204,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
                 return;
         }
 
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            if (!mapAddressBook.count(strAddress))
-                SetAddressBookName(strAddress, "");
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+            if (!pwalletMain->mapAddressBook.count(strAddress))
+                pwalletMain->SetAddressBookName(strAddress, "");
 
         EndModal(true);
     }
@@ -1992,6 +2242,8 @@ CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 n
     fWorkDone = false;
 #ifndef __WXMSW__
     SetSize(1.2 * GetSize().GetWidth(), 1.08 * GetSize().GetHeight());
+#else
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
 
     SetTitle(strprintf(_("Sending %s to %s"), FormatMoney(nPrice).c_str(), wtx.mapValue["to"].c_str()));
@@ -2138,7 +2390,7 @@ void SendingDialogStartTransfer(void* parg)
 void CSendingDialog::StartTransfer()
 {
     // Make sure we have enough money
-    if (nPrice + nTransactionFee > GetBalance())
+    if (nPrice + nTransactionFee > pwalletMain->GetBalance())
     {
         Error(_("Insufficient funds"));
         return;
@@ -2209,21 +2461,32 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
         // Pay
         if (!Status(_("Creating transaction...")))
             return;
-        if (nPrice + nTransactionFee > GetBalance())
+        if (nPrice + nTransactionFee > pwalletMain->GetBalance())
         {
             Error(_("Insufficient funds"));
             return;
         }
-        CReserveKey reservekey;
+
+        CReserveKey reservekey(pwalletMain);
         int64 nFeeRequired;
-        if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
+        CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
         {
-            if (nPrice + nFeeRequired > GetBalance())
-                Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
-            else
-                Error(_("Transaction creation failed"));
-            return;
-        }
+            bool fWasLocked = pwalletMain->IsLocked();
+            if (!GetWalletPassphrase())
+                return;
+
+            if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
+            {
+                if (nPrice + nFeeRequired > pwalletMain->GetBalance())
+                    Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
+                else
+                    Error(_("Transaction creation failed"));
+                return;
+            }
+
+            if (fWasLocked)
+                pwalletMain->Lock();
+       }
 
         // Transaction fee
         if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
@@ -2256,7 +2519,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
             return;
 
         // Commit
-        if (!CommitTransaction(wtx, reservekey))
+        if (!pwalletMain->CommitTransaction(wtx, reservekey))
         {
             Error(_("The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
             return;
@@ -2315,6 +2578,10 @@ void CSendingDialog::OnReply3(CDataStream& vRecv)
 
 CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, int nPageIn, bool fDuringSendIn) : CAddressBookDialogBase(parent)
 {
+#ifdef __WXMSW__
+    SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
+#endif
+
     // Set initially selected page
     wxNotebookEvent event;
     event.SetSelection(nPageIn);
@@ -2326,9 +2593,16 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
         m_buttonCancel->Show(false);
 
     // Set Icon
-    wxIcon iconAddressBook;
-    iconAddressBook.CopyFromBitmap(wxBitmap(addressbook16_xpm));
-    SetIcon(iconAddressBook);
+    if (nScaleX == 1.0 && nScaleY == 1.0) // We don't have icons of the proper size otherwise
+    {
+        wxIcon iconAddressBook;
+        iconAddressBook.CopyFromBitmap(wxBitmap(addressbook16_xpm));
+        SetIcon(iconAddressBook);
+    }
+#ifdef __WXMSW__
+    else
+        SetIcon(wxICON(bitcoin));
+#endif
 
     // Init column headers
     m_listCtrlSending->InsertColumn(0, _("Name"), wxLIST_FORMAT_LEFT, 200);
@@ -2339,11 +2613,11 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
     m_listCtrlReceiving->SetFocus();
 
     // Fill listctrl with address book data
-    CRITICAL_BLOCK(cs_mapKeys)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_KeyStore)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             string strAddress = item.first;
             string strName = item.second;
@@ -2402,7 +2676,8 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
     if (event.IsEditCancelled())
         return;
     string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
-    SetAddressBookName(strAddress, string(event.GetText()));
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
     pframeMain->RefreshListCtrl();
 }
 
@@ -2437,7 +2712,8 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
         if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
         {
             string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
-            CWalletDB().EraseName(strAddress);
+            CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+                pwalletMain->DelAddressBookName(strAddress);
             m_listCtrl->DeleteItem(nIndex);
         }
     }
@@ -2496,9 +2772,12 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
     }
 
     // Write back
-    if (strAddress != strAddressOrg)
-        CWalletDB().EraseName(strAddressOrg);
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+    {
+        if (strAddress != strAddressOrg)
+            pwalletMain->DelAddressBookName(strAddressOrg);
+        pwalletMain->SetAddressBookName(strAddress, strName);
+    }
     m_listCtrl->SetItem(nIndex, 1, strAddress);
     m_listCtrl->SetItemText(nIndex, strName);
     pframeMain->RefreshListCtrl();
@@ -2533,12 +2812,23 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
             return;
         strName = dialog.GetValue();
 
-        // Generate new key
-        strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+        CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
+        {
+            bool fWasLocked = pwalletMain->IsLocked();
+            if (!GetWalletPassphrase())
+                return;
+
+            // Generate new key
+            strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
+
+            if (fWasLocked)
+                pwalletMain->Lock();
+        }
     }
 
     // Add to list and select it
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, strName);
     int nIndex = InsertLine(m_listCtrl, strName, strAddress);
     SetSelection(m_listCtrl, nIndex);
     m_listCtrl->SetFocus();
@@ -2844,6 +3134,16 @@ bool CMyApp::OnInit()
     g_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
     g_locale.AddCatalog("bitcoin");
 
+#ifdef __WXMSW__
+    HDC hdc = GetDC(NULL);
+    if (hdc)
+    {
+        nScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0;
+        nScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0;
+        ReleaseDC(NULL, hdc);
+    }
+#endif
+
     return AppInit(argc, argv);
 }