mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-10 22:18:54 +01:00
addr relaying fixes, proxy option and privacy patches, detect connect to self, non-final tx locktime changes, fix hide unconfirmed generated
This commit is contained in:
223
ui.cpp
223
ui.cpp
@@ -497,7 +497,7 @@ string SingleLine(const string& strIn)
|
||||
return strOut;
|
||||
}
|
||||
|
||||
void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
{
|
||||
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
|
||||
int64 nCredit = wtx.GetCredit();
|
||||
@@ -506,14 +506,11 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
uint256 hash = wtx.GetHash();
|
||||
string strStatus = FormatTxStatus(wtx);
|
||||
map<string, string> mapValue = wtx.mapValue;
|
||||
wtx.nLinesDisplayed = 1;
|
||||
|
||||
// Filter
|
||||
if (wtx.IsCoinBase())
|
||||
{
|
||||
// View->Show Generated
|
||||
if (!fShowGenerated)
|
||||
return;
|
||||
|
||||
// Don't show generated coin until confirmed by at least one block after it
|
||||
// so we don't get the user's hopes up until it looks like it's probably accepted.
|
||||
//
|
||||
@@ -527,10 +524,13 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
//
|
||||
if (wtx.GetDepthInMainChain() < 2)
|
||||
{
|
||||
// In case it was previously displayed
|
||||
DeleteLine(hash);
|
||||
return;
|
||||
wtx.nLinesDisplayed = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// View->Show Generated
|
||||
if (!fShowGenerated)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the block the tx is in
|
||||
@@ -644,6 +644,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
// Debit
|
||||
//
|
||||
int64 nTxFee = nDebit - wtx.GetValueOut();
|
||||
wtx.nLinesDisplayed = 0;
|
||||
for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
|
||||
{
|
||||
const CTxOut& txout = wtx.vout[nOut];
|
||||
@@ -685,6 +686,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
SingleLine(strDescription),
|
||||
FormatMoney(-nValue, true),
|
||||
"");
|
||||
wtx.nLinesDisplayed++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -706,12 +708,14 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMainFrame::RefreshStatus()
|
||||
{
|
||||
static int nLastTop;
|
||||
int nTop = m_listCtrl->GetTopItem();
|
||||
int nTop = max((int)m_listCtrl->GetTopItem(), 0);
|
||||
if (nTop == nLastTop && pindexBestLast == pindexBest)
|
||||
return;
|
||||
|
||||
@@ -729,7 +733,7 @@ void CMainFrame::RefreshStatus()
|
||||
nLastTop = nTop;
|
||||
pindexBestLast = pindexBest;
|
||||
|
||||
for (int nIndex = nStart; nIndex < nEnd; nIndex++)
|
||||
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);
|
||||
@@ -738,9 +742,12 @@ void CMainFrame::RefreshStatus()
|
||||
printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
|
||||
continue;
|
||||
}
|
||||
const CWalletTx& wtx = (*mi).second;
|
||||
CWalletTx& wtx = (*mi).second;
|
||||
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
|
||||
InsertTransaction(wtx, false, nIndex);
|
||||
{
|
||||
if (!InsertTransaction(wtx, false, nIndex))
|
||||
m_listCtrl->DeleteItem(nIndex--);
|
||||
}
|
||||
else
|
||||
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
|
||||
}
|
||||
@@ -801,6 +808,9 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
|
||||
}
|
||||
|
||||
printf("RefreshListCtrl done\n");
|
||||
|
||||
// Update transaction total display
|
||||
MainFrameRepaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -834,31 +844,54 @@ void DelayedRepaint(void* parg)
|
||||
return;
|
||||
fOneThread = true;
|
||||
Sleep(1000);
|
||||
printf("DelayedRepaint()\n");
|
||||
MainFrameRepaint();
|
||||
fOneThread = false;
|
||||
}
|
||||
|
||||
void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
||||
{
|
||||
if (ptaskbaricon)
|
||||
ptaskbaricon->UpdateTooltip();
|
||||
|
||||
// Update listctrl contents
|
||||
if (!vWalletUpdated.empty())
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
bool fInserted = false;
|
||||
foreach(uint256 hash, vWalletUpdated)
|
||||
{
|
||||
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
|
||||
if (mi != mapWallet.end())
|
||||
InsertTransaction((*mi).second, false);
|
||||
fInserted |= InsertTransaction((*mi).second, false);
|
||||
}
|
||||
m_listCtrl->ScrollList(0, INT_MAX);
|
||||
vWalletUpdated.clear();
|
||||
if (fInserted)
|
||||
m_listCtrl->ScrollList(0, INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
// Update status column of visible items only
|
||||
RefreshStatus();
|
||||
|
||||
// Balance total
|
||||
bool fRefreshed = false;
|
||||
static int nTransactionCount;
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
fRefreshed = true;
|
||||
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
|
||||
|
||||
// Count hidden and multi-line transactions
|
||||
nTransactionCount = 0;
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx& wtx = (*it).second;
|
||||
nTransactionCount += wtx.nLinesDisplayed;
|
||||
}
|
||||
}
|
||||
|
||||
// Update status bar
|
||||
string strGen = "";
|
||||
if (fGenerateBitcoins)
|
||||
@@ -867,17 +900,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
|
||||
strGen = "(not connected)";
|
||||
m_statusBar->SetStatusText(strGen, 1);
|
||||
|
||||
string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, m_listCtrl->GetItemCount());
|
||||
string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
|
||||
m_statusBar->SetStatusText(strStatus, 2);
|
||||
|
||||
// Balance total
|
||||
bool fRefreshed = false;
|
||||
TRY_CRITICAL_BLOCK(cs_mapWallet)
|
||||
{
|
||||
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
|
||||
fRefreshed = true;
|
||||
}
|
||||
|
||||
// mapWallet was locked, try again later
|
||||
if (!vWalletUpdated.empty() || !fRefreshed)
|
||||
_beginthread(DelayedRepaint, 0, NULL);
|
||||
@@ -1350,6 +1375,14 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
|
||||
m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);
|
||||
m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);
|
||||
fTmpMinimizeOnClose = fMinimizeOnClose;
|
||||
m_checkBoxUseProxy->SetValue(fUseProxy);
|
||||
m_textCtrlProxyIP->Enable(fUseProxy);
|
||||
m_textCtrlProxyPort->Enable(fUseProxy);
|
||||
m_staticTextProxyIP->Enable(fUseProxy);
|
||||
m_staticTextProxyPort->Enable(fUseProxy);
|
||||
m_textCtrlProxyIP->SetValue(addrProxy.ToStringIP());
|
||||
m_textCtrlProxyPort->SetValue(addrProxy.ToStringPort());
|
||||
|
||||
m_buttonOK->SetFocus();
|
||||
}
|
||||
|
||||
@@ -1395,6 +1428,34 @@ void COptionsDialog::OnCheckBoxMinimizeToTray(wxCommandEvent& event)
|
||||
|
||||
}
|
||||
|
||||
void COptionsDialog::OnCheckBoxUseProxy(wxCommandEvent& event)
|
||||
{
|
||||
m_textCtrlProxyIP->Enable(event.IsChecked());
|
||||
m_textCtrlProxyPort->Enable(event.IsChecked());
|
||||
m_staticTextProxyIP->Enable(event.IsChecked());
|
||||
m_staticTextProxyPort->Enable(event.IsChecked());
|
||||
}
|
||||
|
||||
CAddress COptionsDialog::GetProxyAddr()
|
||||
{
|
||||
// Be careful about byte order, addr.ip and addr.port are big endian
|
||||
CAddress addr(m_textCtrlProxyIP->GetValue() + ":" + m_textCtrlProxyPort->GetValue());
|
||||
if (addr.ip == INADDR_NONE)
|
||||
addr.ip = addrProxy.ip;
|
||||
int nPort = atoi(m_textCtrlProxyPort->GetValue());
|
||||
addr.port = htons(nPort);
|
||||
if (nPort <= 0 || nPort > USHRT_MAX)
|
||||
addr.port = addrProxy.port;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void COptionsDialog::OnKillFocusProxy(wxFocusEvent& event)
|
||||
{
|
||||
m_textCtrlProxyIP->SetValue(GetProxyAddr().ToStringIP());
|
||||
m_textCtrlProxyPort->SetValue(GetProxyAddr().ToStringPort());
|
||||
}
|
||||
|
||||
|
||||
void COptionsDialog::OnButtonOK(wxCommandEvent& event)
|
||||
{
|
||||
OnButtonApply(event);
|
||||
@@ -1446,6 +1507,18 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
|
||||
fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose);
|
||||
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
|
||||
}
|
||||
|
||||
if (fUseProxy != m_checkBoxUseProxy->GetValue())
|
||||
{
|
||||
fUseProxy = m_checkBoxUseProxy->GetValue();
|
||||
walletdb.WriteSetting("fUseProxy", fUseProxy);
|
||||
}
|
||||
|
||||
if (addrProxy != GetProxyAddr())
|
||||
{
|
||||
addrProxy = GetProxyAddr();
|
||||
walletdb.WriteSetting("addrProxy", addrProxy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1657,7 +1730,7 @@ CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 n
|
||||
nPrice = nPriceIn;
|
||||
wtx = wtxIn;
|
||||
start = wxDateTime::UNow();
|
||||
strStatus = "";
|
||||
memset(pszStatus, 0, sizeof(pszStatus));
|
||||
fCanCancel = true;
|
||||
fAbort = false;
|
||||
fSuccess = false;
|
||||
@@ -1721,10 +1794,10 @@ void CSendingDialog::OnButtonCancel(wxCommandEvent& event)
|
||||
|
||||
void CSendingDialog::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
if (strStatus.size() > 130)
|
||||
m_textCtrlStatus->SetValue(string("\n") + strStatus);
|
||||
if (strlen(pszStatus) > 130)
|
||||
m_textCtrlStatus->SetValue(string("\n") + pszStatus);
|
||||
else
|
||||
m_textCtrlStatus->SetValue(string("\n\n") + strStatus);
|
||||
m_textCtrlStatus->SetValue(string("\n\n") + pszStatus);
|
||||
m_staticTextSending->SetFocus();
|
||||
if (!fCanCancel)
|
||||
m_buttonCancel->Enable(false);
|
||||
@@ -1736,7 +1809,7 @@ void CSendingDialog::OnPaint(wxPaintEvent& event)
|
||||
}
|
||||
if (fAbort && fCanCancel && IsShown())
|
||||
{
|
||||
strStatus = "CANCELLED";
|
||||
strcpy(pszStatus, "CANCELLED");
|
||||
m_buttonOK->Enable(true);
|
||||
m_buttonOK->SetFocus();
|
||||
m_buttonCancel->Enable(false);
|
||||
@@ -1777,7 +1850,8 @@ bool CSendingDialog::Status()
|
||||
}
|
||||
if (fAbort && fCanCancel)
|
||||
{
|
||||
strStatus = "CANCELLED";
|
||||
memset(pszStatus, 0, 10);
|
||||
strcpy(pszStatus, "CANCELLED");
|
||||
Repaint();
|
||||
fWorkDone = true;
|
||||
return false;
|
||||
@@ -1789,7 +1863,12 @@ bool CSendingDialog::Status(const string& str)
|
||||
{
|
||||
if (!Status())
|
||||
return false;
|
||||
strStatus = str;
|
||||
|
||||
// This can be read by the UI thread at any time,
|
||||
// so copy in a way that can be read cleanly at all times.
|
||||
memset(pszStatus, 0, min(str.size()+1, sizeof(pszStatus)));
|
||||
strlcpy(pszStatus, str.c_str(), sizeof(pszStatus));
|
||||
|
||||
Repaint();
|
||||
return true;
|
||||
}
|
||||
@@ -1950,8 +2029,8 @@ void CSendingDialog::OnReply3(CDataStream& vRecv)
|
||||
if (nRet > 0)
|
||||
{
|
||||
Error("The payment was sent, but the recipient was unable to verify it.\n"
|
||||
"The transaction is recorded and will credit to the recipient if it is valid,\n"
|
||||
"but without comment information.");
|
||||
"The transaction is recorded and will credit to the recipient,\n"
|
||||
"but the comment information will be blank.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3092,6 +3171,7 @@ END_EVENT_TABLE()
|
||||
|
||||
void CMyTaskBarIcon::Show(bool fShow)
|
||||
{
|
||||
static char pszPrevTip[200];
|
||||
if (fShow)
|
||||
{
|
||||
string strTooltip = "Bitcoin";
|
||||
@@ -3099,10 +3179,17 @@ void CMyTaskBarIcon::Show(bool fShow)
|
||||
strTooltip = "Bitcoin - Generating";
|
||||
if (fGenerateBitcoins && vNodes.empty())
|
||||
strTooltip = "Bitcoin - (not connected)";
|
||||
SetIcon(wxICON(bitcoin), strTooltip);
|
||||
|
||||
// Optimization, only update when changed, using char array to be reentrant
|
||||
if (strncmp(pszPrevTip, strTooltip.c_str(), sizeof(pszPrevTip)-1) != 0)
|
||||
{
|
||||
strlcpy(pszPrevTip, strTooltip.c_str(), sizeof(pszPrevTip));
|
||||
SetIcon(wxICON(bitcoin), strTooltip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(pszPrevTip, "", sizeof(pszPrevTip));
|
||||
RemoveIcon();
|
||||
}
|
||||
}
|
||||
@@ -3301,12 +3388,12 @@ bool CMyApp::OnInit2()
|
||||
if (mapArgs.count("/datadir"))
|
||||
strSetDataDir = mapArgs["/datadir"];
|
||||
|
||||
if (mapArgs.count("/proxy"))
|
||||
addrProxy = CAddress(mapArgs["/proxy"].c_str());
|
||||
|
||||
if (mapArgs.count("/debug"))
|
||||
fDebug = true;
|
||||
|
||||
if (mapArgs.count("/printtodebugger"))
|
||||
fPrintToDebugger = true;
|
||||
|
||||
if (mapArgs.count("/dropmessages"))
|
||||
{
|
||||
nDropMessagesTest = atoi(mapArgs["/dropmessages"]);
|
||||
@@ -3380,6 +3467,20 @@ bool CMyApp::OnInit2()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mapArgs.count("/proxy"))
|
||||
{
|
||||
fUseProxy = true;
|
||||
addrProxy = CAddress(mapArgs["/proxy"].c_str());
|
||||
if (addrProxy.ip == INADDR_NONE)
|
||||
{
|
||||
wxMessageBox("Invalid /proxy address", "Bitcoin");
|
||||
OnExit();
|
||||
}
|
||||
CWalletDB walletdb;
|
||||
walletdb.WriteSetting("fUseProxy", fUseProxy);
|
||||
walletdb.WriteSetting("addrProxy", addrProxy);
|
||||
}
|
||||
|
||||
if (mapArgs.count("/gen"))
|
||||
{
|
||||
if (mapArgs["/gen"].empty())
|
||||
@@ -3404,7 +3505,7 @@ bool CMyApp::OnInit2()
|
||||
return false;
|
||||
}
|
||||
|
||||
//RandAddSeedPerfmon();
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
if (!StartNode(strErrors))
|
||||
wxMessageBox(strErrors, "Bitcoin");
|
||||
@@ -3514,7 +3615,7 @@ void CMyApp::OnFatalException()
|
||||
|
||||
void MainFrameRepaint()
|
||||
{
|
||||
// This is called by network code that shouldn't access pframeMain and ptaskbaricon
|
||||
// This is called by network code that shouldn't access pframeMain
|
||||
// directly because it could still be running after the UI is closed.
|
||||
if (pframeMain)
|
||||
{
|
||||
@@ -3523,20 +3624,47 @@ void MainFrameRepaint()
|
||||
pframeMain->Refresh();
|
||||
pframeMain->AddPendingEvent(event);
|
||||
}
|
||||
if (ptaskbaricon)
|
||||
ptaskbaricon->UpdateTooltip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
|
||||
|
||||
string MyGetSpecialFolderPath(int nFolder, bool fCreate)
|
||||
{
|
||||
char pszPath[MAX_PATH+100] = "";
|
||||
|
||||
// SHGetSpecialFolderPath is not usually available on NT 4.0
|
||||
HMODULE hShell32 = LoadLibrary("shell32.dll");
|
||||
if (hShell32)
|
||||
{
|
||||
PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
|
||||
(PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
|
||||
if (pSHGetSpecialFolderPath)
|
||||
(*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
|
||||
FreeModule(hShell32);
|
||||
}
|
||||
|
||||
// Backup option
|
||||
if (pszPath[0] == '\0')
|
||||
{
|
||||
if (nFolder == CSIDL_STARTUP)
|
||||
{
|
||||
strcpy(pszPath, getenv("USERPROFILE"));
|
||||
strcat(pszPath, "\\Start Menu\\Programs\\Startup");
|
||||
}
|
||||
else if (nFolder == CSIDL_APPDATA)
|
||||
{
|
||||
strcpy(pszPath, getenv("APPDATA"));
|
||||
}
|
||||
}
|
||||
|
||||
return pszPath;
|
||||
}
|
||||
|
||||
string StartupShortcutPath()
|
||||
{
|
||||
// Get the startup folder shortcut path
|
||||
char pszLinkPath[MAX_PATH+100];
|
||||
pszLinkPath[0] = '\0';
|
||||
SHGetSpecialFolderPath(0, pszLinkPath, CSIDL_STARTUP, 0);
|
||||
strcat(pszLinkPath, "\\Bitcoin.lnk");
|
||||
return pszLinkPath;
|
||||
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
|
||||
}
|
||||
|
||||
bool GetStartOnSystemStartup()
|
||||
@@ -3630,7 +3758,8 @@ void ThreadRandSendTest(void* parg)
|
||||
if (GetBalance() < nValue)
|
||||
{
|
||||
wxMessageBox("Out of money ");
|
||||
return;
|
||||
while (GetBalance() < 1000)
|
||||
Sleep(1000);
|
||||
}
|
||||
nValue += (nRep % 100) * CENT;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user