X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fui.cpp;h=1fcfff6cc1244bd93a1b2449c9e8a92507658acf;hb=58ac600b2c94f12309fc5e18933891590dc1eb4c;hp=cca473d82bf964c0c048ff438e75ad4f8a21d274;hpb=af531f0449eae49e0e048218c9dccb3b3a771704;p=novacoin.git diff --git a/src/ui.cpp b/src/ui.cpp index cca473d..1fcfff6 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -1,8 +1,14 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2011 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" +#include "db.h" +#include "init.h" +#include "strlcpy.h" +#include +#include #ifdef _MSC_VER #include #endif @@ -230,16 +236,52 @@ void SetDefaultReceivingAddress(const string& strAddress) return; if (strAddress != pframeMain->m_textCtrlAddress->GetValue()) { - uint160 hash160; - if (!AddressToHash160(strAddress, hash160)) + CBitcoinAddress address(strAddress); + if (!address.IsValid()) return; - if (!mapPubKeys.count(hash160)) + vector vchPubKey; + if (!pwalletMain->GetPubKey(address, vchPubKey)) return; - CWalletDB().WriteDefaultKey(mapPubKeys[hash160]); + pwalletMain->SetDefaultKey(vchPubKey); 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; +} + @@ -285,7 +327,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__ @@ -325,8 +367,13 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) // Fill your address text box vector vchPubKey; - if (CWalletDB("r").ReadDefaultKey(vchPubKey)) - m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey)); + if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey)) + m_textCtrlAddress->SetValue(CBitcoinAddress(vchPubKey).ToString()); + + if (pwalletMain->IsCrypted()) + m_menuOptions->Remove(m_menuOptionsEncryptWallet); + else + m_menuOptions->Remove(m_menuOptionsChangeWalletPassphrase); // Fill listctrl with wallet transactions RefreshListCtrl(); @@ -517,7 +564,7 @@ string FormatTxStatus(const CWalletTx& wtx) // Status if (!wtx.IsFinal()) { - if (wtx.nLockTime < 500000000) + if (wtx.nLockTime < LOCKTIME_THRESHOLD) return strprintf(_("Open for %d blocks"), nBestHeight - wtx.nLockTime); else return strprintf(_("Open until %s"), DateTimeStr(wtx.nLockTime).c_str()); @@ -620,7 +667,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()); @@ -656,26 +703,25 @@ 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 vchPubKey; - if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) + CBitcoinAddress address; + if (ExtractAddress(txout.scriptPubKey, pwalletMain, address)) { - CRITICAL_BLOCK(cs_mapAddressBook) + CRITICAL_BLOCK(pwalletMain->cs_wallet) { //strDescription += _("Received payment to "); //strDescription += _("Received with address "); strDescription += _("Received with: "); - string strAddress = PubKeyToAddress(vchPubKey); - map::iterator mi = mapAddressBook.find(strAddress); - if (mi != mapAddressBook.end() && !(*mi).second.empty()) + map::iterator mi = pwalletMain->mapAddressBook.find(address); + if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty()) { string strLabel = (*mi).second; - strDescription += strAddress.substr(0,12) + "... "; + strDescription += address.ToString().substr(0,12) + "... "; strDescription += "(" + strLabel + ")"; } else - strDescription += strAddress; + strDescription += address.ToString(); } } break; @@ -698,11 +744,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) { @@ -728,9 +774,10 @@ 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; + CBitcoinAddress address; string strAddress; if (!mapValue["to"].empty()) { @@ -740,15 +787,14 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) else { // Sent to Bitcoin Address - uint160 hash160; - if (ExtractHash160(txout.scriptPubKey, hash160)) - strAddress = Hash160ToAddress(hash160); + if (ExtractAddress(txout.scriptPubKey, NULL, address)) + strAddress = address.ToString(); } string strDescription = _("To: "); - CRITICAL_BLOCK(cs_mapAddressBook) - if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty()) - strDescription += mapAddressBook[strAddress] + " "; + CRITICAL_BLOCK(pwalletMain->cs_wallet) + if (pwalletMain->mapAddressBook.count(address) && !pwalletMain->mapAddressBook[address].empty()) + strDescription += pwalletMain->mapAddressBook[address] + " "; strDescription += strAddress; if (!mapValue["message"].empty()) { @@ -787,9 +833,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, @@ -816,16 +862,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event) // Collect list of wallet transactions and sort newest first bool fEntered = false; vector > vSorted; - TRY_CRITICAL_BLOCK(cs_mapWallet) + TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet) { printf("RefreshListCtrl starting\n"); fEntered = true; fRefreshListCtrl = false; - vWalletUpdated.clear(); + pwalletMain->vWalletUpdated.clear(); // Do the newest transactions first - vSorted.reserve(mapWallet.size()); - for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + vSorted.reserve(pwalletMain->mapWallet.size()); + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; unsigned int nTime = UINT_MAX - wtx.GetTxTime(); @@ -844,12 +890,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event) if (fShutdown) return; bool fEntered = false; - TRY_CRITICAL_BLOCK(cs_mapWallet) + TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet) { fEntered = true; uint256& hash = vSorted[i++].second; - map::iterator mi = mapWallet.find(hash); - if (mi != mapWallet.end()) + map::iterator mi = pwalletMain->mapWallet.find(hash); + if (mi != pwalletMain->mapWallet.end()) InsertTransaction((*mi).second, true); } if (!fEntered || i == 100 || i % 500 == 0) @@ -867,10 +913,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event) static int64 nLastTime; if (GetTime() > nLastTime + 30) { - TRY_CRITICAL_BLOCK(cs_mapWallet) + TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet) { nLastTime = GetTime(); - for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { CWalletTx& wtx = (*it).second; if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime()) @@ -891,7 +937,7 @@ void CMainFrame::RefreshStatusColumn() if (nTop == nLastTop && pindexLastBest == pindexBest) return; - TRY_CRITICAL_BLOCK(cs_mapWallet) + TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet) { int nStart = nTop; int nEnd = min(nStart + 100, m_listCtrl->GetItemCount()); @@ -911,8 +957,8 @@ void CMainFrame::RefreshStatusColumn() for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++) { uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1)); - map::iterator mi = mapWallet.find(hash); - if (mi == mapWallet.end()) + map::iterator mi = pwalletMain->mapWallet.find(hash); + if (mi == pwalletMain->mapWallet.end()) { printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n"); continue; @@ -1009,41 +1055,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_wallet) { string strTop; if (m_listCtrl->GetItemCount()) strTop = (string)m_listCtrl->GetItemText(0); - BOOST_FOREACH(uint256 hash, vWalletUpdated) + BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated) { - map::iterator mi = mapWallet.find(hash); - if (mi != mapWallet.end()) + map::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_wallet) { fPaintedBalance = true; - m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " "); + m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " "); // Count hidden and multi-line transactions nTransactionCount = 0; - for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for (map::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 @@ -1069,7 +1115,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) m_statusBar->SetStatusText(strStatus, 2); // Update receiving address - string strDefaultAddress = PubKeyToAddress(vchDefaultKey); + string strDefaultAddress = CBitcoinAddress(pwalletMain->vchDefaultKey).ToString(); if (m_textCtrlAddress->GetValue() != strDefaultAddress) m_textCtrlAddress->SetValue(strDefaultAddress); } @@ -1117,6 +1163,165 @@ 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.\nBitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."), "Bitcoin"); + + Close(true); +} + +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(); + + 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 @@ -1177,11 +1382,23 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event) return; string strName = dialog.GetValue(); + string strAddress; + + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + // Generate new key - string strAddress = PubKeyToAddress(GetKeyFromKeyPool()); + std::vector newKey; + pwalletMain->GetKeyFromPool(newKey, true); + strAddress = CBitcoinAddress(newKey).ToString(); + + if (fWasLocked) + pwalletMain->Lock(); // Save - SetAddressBookName(strAddress, strName); + CRITICAL_BLOCK(pwalletMain->cs_wallet) + pwalletMain->SetAddressBookName(strAddress, strName); SetDefaultReceivingAddress(strAddress); } @@ -1199,10 +1416,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_wallet) { - map::iterator mi = mapWallet.find(hash); - if (mi == mapWallet.end()) + map::iterator mi = pwalletMain->mapWallet.find(hash); + if (mi == pwalletMain->mapWallet.end()) { printf("CMainFrame::OnListItemActivated() : tx not found in mapWallet\n"); return; @@ -1230,7 +1447,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails #ifdef __WXMSW__ SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight()); #endif - CRITICAL_BLOCK(cs_mapAddressBook) + CRITICAL_BLOCK(pwalletMain->cs_wallet) { string strHTML; strHTML.reserve(4000); @@ -1280,19 +1497,18 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - if (txout.IsMine()) + if (pwalletMain->IsMine(txout)) { - vector vchPubKey; - if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) + CBitcoinAddress address; + if (ExtractAddress(txout.scriptPubKey, pwalletMain, address)) { - string strAddress = PubKeyToAddress(vchPubKey); - if (mapAddressBook.count(strAddress)) + if (pwalletMain->mapAddressBook.count(address)) { strHTML += string() + _("From: ") + _("unknown") + "
"; strHTML += _("To: "); - strHTML += HtmlEscape(strAddress); - if (!mapAddressBook[strAddress].empty()) - strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")"; + strHTML += HtmlEscape(address.ToString()); + if (!pwalletMain->mapAddressBook[address].empty()) + strHTML += _(" (yours, label: ") + pwalletMain->mapAddressBook[address] + ")"; else strHTML += _(" (yours)"); strHTML += "
"; @@ -1314,8 +1530,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails // Online transaction strAddress = wtx.mapValue["to"]; strHTML += _("To: "); - 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) + "
"; } @@ -1330,7 +1546,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 += _("Credit: "); if (wtx.IsInMainChain()) strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity()); @@ -1349,11 +1565,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) { @@ -1362,19 +1578,19 @@ 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()) { // Offline transaction - uint160 hash160; - if (ExtractHash160(txout.scriptPubKey, hash160)) + CBitcoinAddress address; + if (ExtractAddress(txout.scriptPubKey, pwalletMain, address)) { - string strAddress = Hash160ToAddress(hash160); + string strAddress = address.ToString(); strHTML += _("To: "); - if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty()) - strHTML += mapAddressBook[strAddress] + " "; + if (pwalletMain->mapAddressBook.count(address) && !pwalletMain->mapAddressBook[address].empty()) + strHTML += pwalletMain->mapAddressBook[address] + " "; strHTML += strAddress; strHTML += "
"; } @@ -1402,11 +1618,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails // Mixed debit transaction // BOOST_FOREACH(const CTxIn& txin, wtx.vin) - if (txin.IsMine()) - strHTML += _("Debit: ") + FormatMoney(-txin.GetDebit()) + "
"; + if (pwalletMain->IsMine(txin)) + strHTML += _("Debit: ") + FormatMoney(-pwalletMain->GetDebit(txin)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - if (txout.IsMine()) - strHTML += _("Credit: ") + FormatMoney(txout.GetCredit()) + "
"; + if (pwalletMain->IsMine(txout)) + strHTML += _("Credit: ") + FormatMoney(pwalletMain->GetCredit(txout)) + "
"; } } @@ -1432,30 +1648,30 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails { strHTML += "

debug print

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) - if (txin.IsMine()) - strHTML += "Debit: " + FormatMoney(-txin.GetDebit()) + "
"; + if (pwalletMain->IsMine(txin)) + strHTML += "Debit: " + FormatMoney(-pwalletMain->GetDebit(txin)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - if (txout.IsMine()) - strHTML += "Credit: " + FormatMoney(txout.GetCredit()) + "
"; + if (pwalletMain->IsMine(txout)) + strHTML += "Credit: " + FormatMoney(pwalletMain->GetCredit(txout)) + "
"; strHTML += "
Transaction:
"; strHTML += HtmlEscape(wtx.ToString(), true); strHTML += "
Inputs:
"; - CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(pwalletMain->cs_wallet) { BOOST_FOREACH(const CTxIn& txin, wtx.vin) { COutPoint prevout = txin.prevout; - map::iterator mi = mapWallet.find(prevout.hash); - if (mi != mapWallet.end()) + map::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 += "    " + FormatTxStatus(prev) + ", "; - strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "
"; + strHTML = strHTML + "IsMine=" + (pwalletMain->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "
"; } } } @@ -1588,7 +1804,11 @@ void SetStartOnSystemStartup(bool fAutoStart) { if (!fAutoStart) { +#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 + unlink(GetAutostartFilePath().string().c_str()); +#else unlink(GetAutostartFilePath().native_file_string().c_str()); +#endif } else { @@ -1746,7 +1966,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) @@ -1923,41 +2143,59 @@ 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; } // Parse bitcoin address - uint160 hash160; - bool fBitcoinAddress = AddressToHash160(strAddress, hash160); + CBitcoinAddress address(strAddress); + bool fBitcoinAddress = address.IsValid(); if (fBitcoinAddress) { + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + + string strError; CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(pwalletMain->cs_wallet) { // Send to bitcoin address CScript scriptPubKey; - scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey.SetBitcoinAddress(address); - string strError = SendMoney(scriptPubKey, nValue, wtx, true); - if (strError == "") - wxMessageBox(_("Payment sent "), _("Sending...")); - else if (strError == "ABORTED") - return; // leave send dialog open - else - { - wxMessageBox(strError + " ", _("Sending...")); - EndModal(false); - return; - } - } + strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true); + } + if (strError == "") + { + pframeMain->RefreshListCtrl(); + 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 { @@ -1978,9 +2216,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) return; } - CRITICAL_BLOCK(cs_mapAddressBook) - if (!mapAddressBook.count(strAddress)) - SetAddressBookName(strAddress, ""); + CRITICAL_BLOCK(pwalletMain->cs_wallet) + if (!pwalletMain->mapAddressBook.count(address)) + pwalletMain->SetAddressBookName(strAddress, ""); EndModal(true); } @@ -2164,7 +2402,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; @@ -2230,72 +2468,89 @@ void CSendingDialog::OnReply2(CDataStream& vRecv) return; } + // Pay + if (!Status(_("Creating transaction..."))) + return; + if (nPrice + nTransactionFee > pwalletMain->GetBalance()) + { + Error(_("Insufficient funds")); + return; + } + + CReserveKey reservekey(pwalletMain); + int64 nFeeRequired; + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + + bool fTxCreated = false; CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(pwalletMain->cs_wallet) { - // Pay - if (!Status(_("Creating transaction..."))) - return; - if (nPrice + nTransactionFee > GetBalance()) - { - Error(_("Insufficient funds")); - return; - } - CReserveKey reservekey; - int64 nFeeRequired; - if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired)) - { - 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; - } + fTxCreated = pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired); + } + if (!fTxCreated) + { + 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; + } - // Transaction fee - if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this)) - { - Error(_("Transaction aborted")); - return; - } + if (fWasLocked) + pwalletMain->Lock(); - // Make sure we're still connected - CNode* pnode = ConnectNode(addr, 2 * 60 * 60); - if (!pnode) - { - Error(_("Lost connection, transaction cancelled")); - return; - } + // Transaction fee + if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this)) + { + Error(_("Transaction aborted")); + return; + } - // Last chance to cancel - Sleep(50); + // Make sure we're still connected + CNode* pnode = ConnectNode(addr, 2 * 60 * 60); + if (!pnode) + { + Error(_("Lost connection, transaction cancelled")); + return; + } + + // Last chance to cancel + Sleep(50); + if (!Status()) + return; + fCanCancel = false; + if (fAbort) + { + fCanCancel = true; if (!Status()) return; fCanCancel = false; - if (fAbort) - { - fCanCancel = true; - if (!Status()) - return; - fCanCancel = false; - } - if (!Status(_("Sending payment..."))) - return; + } + if (!Status(_("Sending payment..."))) + return; - // Commit - if (!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; - } + // Commit + bool fTxCommitted = false; + CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(pwalletMain->cs_wallet) + { + fTxCommitted = pwalletMain->CommitTransaction(wtx, reservekey); + } + if (!fTxCommitted) + { + 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; + } - // Send payment tx to seller, with response going to OnReply3 via event handler - CWalletTx wtxSend = wtx; - wtxSend.fFromMe = false; - pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this); + // Send payment tx to seller, with response going to OnReply3 via event handler + CWalletTx wtxSend = wtx; + wtxSend.fFromMe = false; + pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this); - Status(_("Waiting for confirmation...")); - MainFrameRepaint(); - } + Status(_("Waiting for confirmation...")); + MainFrameRepaint(); } void SendingDialogOnReply3(void* parg, CDataStream& vRecv) @@ -2376,19 +2631,17 @@ 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_wallet) { string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue(); - BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook) + BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook) { - string strAddress = item.first; + const CBitcoinAddress& address = item.first; string strName = item.second; - uint160 hash160; - bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160)); + bool fMine = pwalletMain->HaveKey(address); wxListCtrl* plistCtrl = fMine ? m_listCtrlReceiving : m_listCtrlSending; - int nIndex = InsertLine(plistCtrl, strName, strAddress); - if (strAddress == (fMine ? strDefaultReceiving : string(strInitSelected))) + int nIndex = InsertLine(plistCtrl, strName, address.ToString()); + if (address.ToString() == (fMine ? strDefaultReceiving : string(strInitSelected))) plistCtrl->SetItemState(nIndex, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED); } } @@ -2439,7 +2692,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_wallet) + pwalletMain->SetAddressBookName(strAddress, string(event.GetText())); pframeMain->RefreshListCtrl(); } @@ -2474,7 +2728,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_wallet) + pwalletMain->DelAddressBookName(strAddress); m_listCtrl->DeleteItem(nIndex); } } @@ -2493,8 +2748,8 @@ void CAddressBookDialog::OnButtonCopy(wxCommandEvent& event) bool CAddressBookDialog::CheckIfMine(const string& strAddress, const string& strTitle) { - uint160 hash160; - bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160)); + CBitcoinAddress address(strAddress); + bool fMine = address.IsValid() && pwalletMain->HaveKey(address); if (fMine) wxMessageBox(_("This is one of your own addresses for receiving payments and cannot be entered in the address book. "), strTitle); return fMine; @@ -2533,9 +2788,12 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event) } // Write back - if (strAddress != strAddressOrg) - CWalletDB().EraseName(strAddressOrg); - SetAddressBookName(strAddress, strName); + CRITICAL_BLOCK(pwalletMain->cs_wallet) + { + if (strAddress != strAddressOrg) + pwalletMain->DelAddressBookName(strAddressOrg); + pwalletMain->SetAddressBookName(strAddress, strName); + } m_listCtrl->SetItem(nIndex, 1, strAddress); m_listCtrl->SetItemText(nIndex, strName); pframeMain->RefreshListCtrl(); @@ -2570,12 +2828,22 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event) return; strName = dialog.GetValue(); + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + // Generate new key - strAddress = PubKeyToAddress(GetKeyFromKeyPool()); + std::vector newKey; + pwalletMain->GetKeyFromPool(newKey, true); + strAddress = CBitcoinAddress(newKey).ToString(); + + if (fWasLocked) + pwalletMain->Lock(); } // Add to list and select it - SetAddressBookName(strAddress, strName); + CRITICAL_BLOCK(pwalletMain->cs_wallet) + pwalletMain->SetAddressBookName(strAddress, strName); int nIndex = InsertLine(m_listCtrl, strName, strAddress); SetSelection(m_listCtrl, nIndex); m_listCtrl->SetFocus();