Compare commits

...

9 Commits

Author SHA1 Message Date
s_nakamoto
42605ce8bc better prevention of inventory relaying during initial download,
message checksum between nodes with 0.2.9 or higher,
optimization level up from -O0 to -O2,
rpc functions: setlabel, getlabel, getaddressesbylabel, getreceivedbyaddress, getreceivedbylabel, listreceivedbyaddress, listreceivedbylabel
 -- version 0.2.9

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@78 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-05-26 00:05:26 +00:00
s_nakamoto
124baa4ccb build-osx.txt build instructions and makefile.osx from Laszlo
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@77 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-05-25 23:58:27 +00:00
s_nakamoto
2d98de1b3a Mac OS build fixes by laszlo
-- version 0.2.8

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@76 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-05-19 00:26:56 +00:00
s_nakamoto
966cca4bd4 misc
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@75 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-03-05 02:55:09 +00:00
s_nakamoto
2cffa7ce31 fixed runaway memory alloc bug on 64-bit in ParseString found by sirius-m
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@74 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-03-05 01:13:27 +00:00
s_nakamoto
d7d80a74d5 fix unsafe string handling in wxGetTranslation
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@73 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-28 15:00:32 +00:00
s_nakamoto
6557910ccf wx/utils.h and wx/clipbrd.h not needed on bitcoind wxbase build
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@72 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-26 16:09:43 +00:00
s_nakamoto
c2430126d7 GUI-less build target bitcoind that links to wxBase and shouldn't need GTK,
split init and shutdown from ui.cpp into init.cpp,
support wxUSE_GUI=0
-- version 0.2.7

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@71 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-25 21:55:27 +00:00
s_nakamoto
cb420a1dfc run as daemon without GUI,
hooked wxApp::Initialize to ignore gtk-init-check failure if no GUI,
fork to daemonize,
rpc getinfo, getconnectioncount, getbalance, getgenerate, setgenerate,
-- version 0.2.6

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@70 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-23 22:01:39 +00:00
23 changed files with 1675 additions and 890 deletions

209
build-osx.txt Normal file
View File

@@ -0,0 +1,209 @@
Mac OS X build instructions
Laszlo Hanyecz (solar@heliacal.net)
Tested on 10.5 and 10.6 intel. PPC is not supported because it's big-endian.
All of the commands should be executed in Terminal.app.. it's in
/Applications/Utilities
You need to install XCode with all the options checked so that the compiler
and everything is available in /usr not just /Developer
I think it comes on the DVD but you can get the current version from
http://developer.apple.com
1. Pick a directory to work inside.. something like ~/bitcoin works. The
structure I use looks like this:
(~ is your home directory)
~/bitcoin
~/bitcoin/trunk # source code
~/bitcoin/deps # dependencies.. like libraries and headers needed to compile
~/bitcoin/Bitcoin.app # the application bundle where you can run the app
Just execute: mkdir ~/bitcoin
This will create the top dir for you..
WARNING: do not use the ~ notation with the configure scripts.. use the full
name of the directory, for example /Users/james/bitcoin/deps for a user named
'james'. In my examples I am using 'macosuser' so make sure you change that.
2. Check out the trunk version of the bitcoin code from subversion:
cd ~/bitcoin
svn checkout https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk
This will make ~/bitcoin/trunk for you with all the files from subversion.
3. Get and build the dependencies
Boost
-----
Download from http://www.boost.org/users/download/
I'm assuming it ended up in ~/Downloads..
mkdir ~/bitcoin/deps
cd ~/bitcoin/deps
tar xvjf ~/Downloads/boost_1_42_0.tar.bz2
cd boost_1_42_0
./bootstrap.sh
./bjam architecture=combined address-model=32_64 macosx-version=10.6 macosx-version-min=10.5 link=static runtime-link=static --toolset=darwin --prefix=/Users/macosuser/bitcoin/deps install
This part takes a while.. use your judgement and fix it if something doesn't
build for some reason.
Change the prefix to whatever your directory is (my username in this example
is macosuser). I'm also running on 10.6 so i have macosx-version=10.6 change
to 10.5 if you're using leopard.
This is what my output looked like at the end:
...failed updating 2 targets...
...skipped 144 targets...
...updated 8074 targets...
OpenSSL
-------
Download from http://www.openssl.org/source/
We would like to build this as a 32 bit/64 bit library so we actually build it
2 times and join it together here.. If you downloaded with safari it already
uncompressed it so it will just be a tar not a tar.gz
cd ~/bitcoin/deps
tar xvf ~/Downloads/openssl-1.0.0.tar
mv openssl-1.0.0 openssl-1.0.0-i386
tar xvf ~/Downloads/openssl-1.0.0.tar
mv openssl-1.0.0 openssl-1.0.0-x86_64
# build i386 (32 bit intel) binary
cd openssl-1.0.0-i386
./Configure --prefix=/Users/macosuser/bitcoin/deps --openssldir=/Users/macosuser/deps/openssl darwin-i386-cc && make
make install # only do this on one of the architectures, to install the headers
cd ..
# build x86_64 (64 bit intel) binary
cd openssl-1.0.0-x86_64
./Configure --prefix=/Users/macosuser/bitcoin/deps --openssldir=/Users/macosuser/deps/openssl darwin64-x86_64-cc && make
cd ..
# combine the libs
cd ~/bitcoin/deps
lipo -arch i386 openssl-1.0.0-i386/libcrypto.a -arch x86_64 openssl-1.0.0-x86_64/libcrypto.a -o lib/libcrypto.a -create
lipo -arch i386 openssl-1.0.0-i386/libssl.a -arch x86_64 openssl-1.0.0-x86_64/libssl.a -o lib/libssl.a -create
Verify your binaries
file lib/libcrypto.a
output should look like this:
ib/libcrypto.a: Mach-O universal binary with 2 architectures
lib/libcrypto.a (for architecture i386): current ar archive random library
lib/libcrypto.a (for architecture x86_64): current ar archive random library
Berkeley DB
-----------
Download from http://freshmeat.net/projects/berkeleydb/
cd ~/bitcoin/deps
tar xvf ~/Downloads/db-4.8.26.tar
cd db-4.8.26/build_unix
../dist/configure --prefix=/Users/macosuser/bitcoin/deps --enable-cxx && make && make install
wxWidgets
---------
This is the big one..
Check it out from svn
cd ~/bitcoin/deps
svn checkout http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk wxWidgets-trunk
This will make a wxWidgets-trunk directory in deps.
Use this script snippet, change your prefix to whatever your dir is:
PREFIX=~/bitcoin/deps
SRCDIR="$PREFIX/wxWidgets-trunk"
BUILDDIR="$SRCDIR/macbuild"
cd "$PREFIX" &&
#svn checkout http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk wxWidgets-trunk &&
cd "$SRCDIR" &&
[ -f include/wx/hashmap.h.orig ] || cp include/wx/hashmap.h include/wx/hashmap.h.orig &&
sed 's/if wxUSE_STL/if 0 \&\& wxUSE_STL/g' < include/wx/hashmap.h.orig > include/wx/hashmap.h &&
[ -f include/wx/hashset.h.orig ] || cp include/wx/hashset.h include/wx/hashset.h.orig &&
sed 's/if wxUSE_STL/if 0 \&\& wxUSE_STL/g' < include/wx/hashset.h.orig > include/wx/hashset.h &&
rm -vrf "$BUILDDIR" &&
mkdir "$BUILDDIR" &&
cd "$BUILDDIR" &&
../configure --prefix="$PREFIX" \
--with-osx_cocoa \
--disable-shared \
--disable-debug_flag \
--with-macosx-version-min=10.5 \
--enable-stl \
--enable-utf8 \
--enable-universal_binary \
--with-libjpeg=builtin \
--with-libpng=builtin \
--with-regex=builtin \
--with-libtiff=builtin \
--with-zlib=builtin \
--with-expat=builtin \
--with-macosx-sdk=/Developer/SDKs/MacOSX10.5.sdk &&
find . -name Makefile |
while read i; do
echo $i;
sed 's/-arch i386/-arch i386 -arch x86_64/g' < "$i" > "$i".new &&
mv "$i" "$i".old &&
mv "$i".new "$i";
done
make &&
make install
Now you should be able to build bitcoin
cd ~/bitcoin/trunk
make -f makefile.osx bitcoin
Before you can run it, you need to create an application bundle for Mac OS.
Create the directories in terminal using mkdir and copy the files into place.
They are available at http://heliacal.net/~solar/bitcoin/mac-build/
You need the Info.plist and the .ins file. The Contents/MacOS/bitcoin file is
the output of the build.
Your directory structure should look like this:
Bitcoin.app
Bitcoin.app/Contents
Bitcoin.app/Contents/Info.plist
Bitcoin.app/Contents/MacOS
Bitcoin.app/Contents/MacOS/bitcoin
Bitcoin.app/Contents/Resources
Bitcoin.app/Contents/Resources/BitcoinAppIcon.icns
To run it you can just click the Bitcoin.app in Finder, or just do open
~/bitcoin/Bitcoin.app
If you want to run it with arguments you can just run it without backgrounding
by specifying the full name in terminal:
~/bitcoin/Bitcoin.app/Contents/MacOS/bitcoin -addnode=192.75.207.66

2
db.h
View File

@@ -328,6 +328,8 @@ public:
bool EraseName(const string& strAddress)
{
// This should only be used for sending addresses, never for receiving addresses,
// receiving addresses must always have an address book entry if they're not change return.
CRITICAL_BLOCK(cs_mapAddressBook)
mapAddressBook.erase(strAddress);
nWalletDBUpdated++;

View File

@@ -19,11 +19,13 @@
#define WIN32_LEAN_AND_MEAN 1
#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
#include <wx/wx.h>
#include <wx/clipbrd.h>
#include <wx/snglinst.h>
#include <wx/taskbar.h>
#include <wx/stdpaths.h>
#include <wx/snglinst.h>
#if wxUSE_GUI
#include <wx/utils.h>
#include <wx/clipbrd.h>
#include <wx/taskbar.h>
#endif
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
@@ -100,8 +102,11 @@ using namespace boost;
#include "irc.h"
#include "main.h"
#include "rpc.h"
#if wxUSE_GUI
#include "uibase.h"
#endif
#include "ui.h"
#include "init.h"
#include "xpm/addressbook16.xpm"
#include "xpm/addressbook20.xpm"

630
init.cpp Normal file
View File

@@ -0,0 +1,630 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
void ExitTimeout(void* parg)
{
#ifdef __WXMSW__
Sleep(5000);
ExitProcess(0);
#endif
}
void Shutdown(void* parg)
{
static CCriticalSection cs_Shutdown;
static bool fTaken;
bool fFirstThread;
CRITICAL_BLOCK(cs_Shutdown)
{
fFirstThread = !fTaken;
fTaken = true;
}
static bool fExit;
if (fFirstThread)
{
fShutdown = true;
nTransactionsUpdated++;
DBFlush(false);
StopNode();
DBFlush(true);
CreateThread(ExitTimeout, NULL);
Sleep(50);
printf("Bitcoin exiting\n\n");
fExit = true;
exit(0);
}
else
{
while (!fExit)
Sleep(500);
Sleep(100);
ExitThread(0);
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Startup folder
//
#ifdef __WXMSW__
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 = LoadLibraryA("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()
{
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
}
bool GetStartOnSystemStartup()
{
return wxFileExists(StartupShortcutPath());
}
void SetStartOnSystemStartup(bool fAutoStart)
{
// If the shortcut exists already, remove it for updating
remove(StartupShortcutPath().c_str());
if (fAutoStart)
{
CoInitialize(NULL);
// Get a pointer to the IShellLink interface.
IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**>(&psl));
if (SUCCEEDED(hres))
{
// Get the current executable path
TCHAR pszExePath[MAX_PATH];
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
// Set the path to the shortcut target
psl->SetPath(pszExePath);
PathRemoveFileSpec(pszExePath);
psl->SetWorkingDirectory(pszExePath);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
// Query IShellLink for the IPersistFile interface for
// saving the shortcut in persistent storage.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile,
reinterpret_cast<void**>(&ppf));
if (SUCCEEDED(hres))
{
WCHAR pwsz[MAX_PATH];
// Ensure that the string is ANSI.
MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(pwsz, TRUE);
ppf->Release();
}
psl->Release();
}
CoUninitialize();
}
}
#else
bool GetStartOnSystemStartup() { return false; }
void SetStartOnSystemStartup(bool fAutoStart) { }
#endif
//////////////////////////////////////////////////////////////////////////////
//
// CMyApp
//
// Define a new application
class CMyApp: public wxApp
{
public:
wxLocale m_locale;
CMyApp(){};
~CMyApp(){};
bool OnInit();
bool OnInit2();
int OnExit();
// Hook Initialize so we can start without GUI
virtual bool Initialize(int& argc, wxChar** argv);
// 2nd-level exception handling: we get all the exceptions occurring in any
// event handler here
virtual bool OnExceptionInMainLoop();
// 3rd, and final, level exception handling: whenever an unhandled
// exception is caught, this function is called
virtual void OnUnhandledException();
// and now for something different: this function is called in case of a
// crash (e.g. dereferencing null pointer, division by 0, ...)
virtual void OnFatalException();
};
IMPLEMENT_APP(CMyApp)
bool CMyApp::Initialize(int& argc, wxChar** argv)
{
if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
wxString(argv[1]) != "start")
{
fCommandLine = true;
}
else if (!fGUI)
{
fDaemon = true;
}
else
{
// wxApp::Initialize will remove environment-specific parameters,
// so it's too early to call ParseParameters yet
for (int i = 1; i < argc; i++)
{
wxString str = argv[i];
#ifdef __WXMSW__
if (str.size() >= 1 && str[0] == '/')
str[0] = '-';
str = str.MakeLower();
#endif
// haven't decided which argument to use for this yet
if (str == "-daemon" || str == "-d" || str == "start")
fDaemon = true;
}
}
#ifdef __WXGTK__
if (fDaemon || fCommandLine)
{
// Call the original Initialize while suppressing error messages
// and ignoring failure. If unable to initialize GTK, it fails
// near the end so hopefully the last few things don't matter.
{
wxLogNull logNo;
wxApp::Initialize(argc, argv);
}
if (fDaemon)
{
// Daemonize
pid_t pid = fork();
if (pid < 0)
{
fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
return false;
}
if (pid > 0)
pthread_exit((void*)0);
}
return true;
}
#endif
return wxApp::Initialize(argc, argv);
}
bool CMyApp::OnInit()
{
bool fRet = false;
try
{
fRet = OnInit2();
}
catch (std::exception& e) {
PrintException(&e, "OnInit()");
} catch (...) {
PrintException(NULL, "OnInit()");
}
if (!fRet)
Shutdown(NULL);
return fRet;
}
extern int g_isPainting;
bool CMyApp::OnInit2()
{
#ifdef _MSC_VER
// Turn off microsoft heap dump noise
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif
#if _MSC_VER >= 1400
// Disable confusing "helpful" text message on abort, ctrl-c
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif
#if defined(__WXMSW__) && defined(__WXDEBUG__) && wxUSE_GUI
// Disable malfunctioning wxWidgets debug assertion
g_isPainting = 10000;
#endif
#if wxUSE_GUI
wxImage::AddHandler(new wxPNGHandler);
#endif
#if defined(__WXMSW__ ) || defined(__WXMAC__)
SetAppName("Bitcoin");
#else
SetAppName("bitcoin");
#endif
#ifndef __WXMSW__
umask(077);
#endif
#ifdef __WXMSW__
#if wxUSE_UNICODE
// Hack to set wxConvLibc codepage to UTF-8 on Windows,
// may break if wxMBConv_win32 implementation in strconv.cpp changes.
class wxMBConv_win32 : public wxMBConv
{
public:
long m_CodePage;
size_t m_minMBCharWidth;
};
if (((wxMBConv_win32*)&wxConvLibc)->m_CodePage == CP_ACP)
((wxMBConv_win32*)&wxConvLibc)->m_CodePage = CP_UTF8;
#endif
#endif
// Load locale/<lang>/LC_MESSAGES/bitcoin.mo language file
m_locale.Init(wxLANGUAGE_DEFAULT, 0);
m_locale.AddCatalogLookupPathPrefix("locale");
if (!fWindows)
{
m_locale.AddCatalogLookupPathPrefix("/usr/share/locale");
m_locale.AddCatalogLookupPathPrefix("/usr/local/share/locale");
}
m_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
m_locale.AddCatalog("bitcoin");
//
// Parameters
//
if (fCommandLine)
{
int ret = CommandLineRPC(argc, argv);
exit(ret);
}
ParseParameters(argc, argv);
if (mapArgs.count("-?") || mapArgs.count("--help"))
{
wxString strUsage = string() +
_("Usage: bitcoin [options]") + "\t\t\t\t\t\t\n" +
_("Options:\n") +
" -gen \t\t " + _("Generate coins\n") +
" -gen=0 \t\t " + _("Don't generate coins\n") +
" -min \t\t " + _("Start minimized\n") +
" -datadir=<dir> \t " + _("Specify data directory\n") +
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
" -connect=<ip> \t " + _("Connect only to the specified node\n") +
" -? \t\t " + _("This help message\n");
if (fWindows && fGUI)
{
// Remove spaces, the tabs make the columns line up in the message box
for (int i = 0; i < 50; i++)
strUsage.Replace(" \t", "\t");
wxMessageBox(strUsage, "Bitcoin", wxOK);
}
else
{
// Remove tabs
strUsage.Replace("\t", "");
fprintf(stderr, "%s", ((string)strUsage).c_str());
}
return false;
}
if (mapArgs.count("-datadir"))
strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
if (mapArgs.count("-debug"))
fDebug = true;
if (mapArgs.count("-printtodebugger"))
fPrintToDebugger = true;
if (!fDebug && !pszSetDataDir[0])
ShrinkDebugFile();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Bitcoin version 0.%d.%d%s beta, OS version %s\n", VERSION/100, VERSION%100, pszSubVer, ((string)wxGetOsDescription()).c_str());
printf("System default language is %d %s\n", m_locale.GetSystemLanguage(), ((string)m_locale.GetSysName()).c_str());
printf("Language file %s (%s)\n", (string("locale/") + (string)m_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)m_locale.GetLocale()).c_str());
if (mapArgs.count("-loadblockindextest"))
{
CTxDB txdb("r");
txdb.LoadBlockIndex();
PrintBlockTree();
return false;
}
//
// Limit to single instance per user
// Required to protect the database files if we're going to keep deleting log.*
//
#ifdef __WXMSW__
// todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
// maybe should go by whether successfully bind port 8333 instead
wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
for (int i = 0; i < strMutexName.size(); i++)
if (!isalnum(strMutexName[i]))
strMutexName[i] = '.';
wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
if (psingleinstancechecker->IsAnotherRunning())
{
printf("Existing instance found\n");
unsigned int nStart = GetTime();
loop
{
// TODO: find out how to do this in Linux, or replace with wxWidgets commands
// Show the previous instance and exit
HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
if (hwndPrev)
{
if (IsIconic(hwndPrev))
ShowWindow(hwndPrev, SW_RESTORE);
SetForegroundWindow(hwndPrev);
return false;
}
if (GetTime() > nStart + 60)
return false;
// Resume this instance if the other exits
delete psingleinstancechecker;
Sleep(1000);
psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
if (!psingleinstancechecker->IsAnotherRunning())
break;
}
}
#endif
// Bind to the port early so we can tell if another instance is already running.
// This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
string strErrors;
if (!BindListenPort(strErrors))
{
wxMessageBox(strErrors, "Bitcoin");
return false;
}
//
// Load data files
//
if (fDaemon)
fprintf(stdout, "bitcoin server starting\n");
strErrors = "";
int64 nStart;
printf("Loading addresses...\n");
nStart = GetTimeMillis();
if (!LoadAddresses())
strErrors += _("Error loading addr.dat \n");
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading block index...\n");
nStart = GetTimeMillis();
if (!LoadBlockIndex())
strErrors += _("Error loading blkindex.dat \n");
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading wallet...\n");
nStart = GetTimeMillis();
bool fFirstRun;
if (!LoadWallet(fFirstRun))
strErrors += _("Error loading wallet.dat \n");
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Done loading\n");
//// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
printf("mapKeys.size() = %d\n", mapKeys.size());
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
printf("mapWallet.size() = %d\n", mapWallet.size());
printf("mapAddressBook.size() = %d\n", mapAddressBook.size());
if (!strErrors.empty())
{
wxMessageBox(strErrors, "Bitcoin");
return false;
}
// Add wallet transactions that aren't already in a block to mapTransactions
ReacceptWalletTransactions();
//
// Parameters
//
if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
{
PrintBlockTree();
return false;
}
if (mapArgs.count("-printblock"))
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
block.ReadFromDisk(pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
nFound++;
}
}
if (nFound == 0)
printf("No blocks matching %s were found\n", strMatch.c_str());
return false;
}
if (mapArgs.count("-gen"))
{
if (mapArgs["-gen"].empty())
fGenerateBitcoins = true;
else
fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
}
if (mapArgs.count("-proxy"))
{
fUseProxy = true;
addrProxy = CAddress(mapArgs["-proxy"]);
if (!addrProxy.IsValid())
{
wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
return false;
}
}
if (mapArgs.count("-addnode"))
{
foreach(string strAddr, mapMultiArgs["-addnode"])
{
CAddress addr(strAddr, NODE_NETWORK);
addr.nTime = 0; // so it won't relay unless successfully connected
if (addr.IsValid())
AddAddress(addr);
}
}
//
// Create the main window and start the node
//
if (!fDaemon)
CreateMainWindow();
if (!CheckDiskSpace())
return false;
RandAddSeedPerfmon();
if (!CreateThread(StartNode, NULL))
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
if (mapArgs.count("-server") || fDaemon)
CreateThread(ThreadRPCServer, NULL);
if (fFirstRun)
SetStartOnSystemStartup(true);
return true;
}
int CMyApp::OnExit()
{
Shutdown(NULL);
return wxApp::OnExit();
}
bool CMyApp::OnExceptionInMainLoop()
{
try
{
throw;
}
catch (std::exception& e)
{
PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
Sleep(1000);
throw;
}
catch (...)
{
PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
wxLogWarning("Unknown exception");
Sleep(1000);
throw;
}
return true;
}
void CMyApp::OnUnhandledException()
{
// this shows how we may let some exception propagate uncaught
try
{
throw;
}
catch (std::exception& e)
{
PrintException(&e, "CMyApp::OnUnhandledException()");
wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
Sleep(1000);
throw;
}
catch (...)
{
PrintException(NULL, "CMyApp::OnUnhandledException()");
wxLogWarning("Unknown exception");
Sleep(1000);
throw;
}
}
void CMyApp::OnFatalException()
{
wxMessageBox(_("Program has crashed and will terminate. "), "Bitcoin", wxOK | wxICON_ERROR);
}

7
init.h Normal file
View File

@@ -0,0 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
void Shutdown(void* parg);
bool GetStartOnSystemStartup();
void SetStartOnSystemStartup(bool fAutoStart);

View File

@@ -76,6 +76,8 @@ bool RecvLine(SOCKET hSocket, string& strLine)
if (c == '\r')
return true;
strLine += c;
if (strLine.size() >= 9000)
return true;
}
else if (nBytes <= 0)
{
@@ -109,7 +111,7 @@ bool RecvLineIRC(SOCKET hSocket, string& strLine)
return false;
vector<string> vWords;
ParseString(strLine, ' ', vWords);
if (vWords[0] == "PING")
if (vWords.size() >= 1 && vWords[0] == "PING")
{
strLine[1] = 'O';
strLine += '\r';
@@ -156,6 +158,7 @@ bool Wait(int nSeconds)
void ThreadIRCSeed(void* parg)
{
printf("ThreadIRCSeed started\n");
SetThreadPriority(THREAD_PRIORITY_NORMAL);
int nErrorWait = 10;
int nRetryWait = 10;

View File

@@ -55,6 +55,8 @@ int64 nTransactionFee = 0;
CAddress addrIncoming;
int fLimitProcessors = false;
int nLimitProcessors = 1;
int fMinimizeToTray = true;
int fMinimizeOnClose = true;
@@ -1315,11 +1317,10 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
// Check that all transactions are finalized (starting around Mar 2010)
if (nBestHeight > 36000)
foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(nTime))
return error("AcceptBlock() : contains a non-final transaction");
// Check that all transactions are finalized
foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(nTime))
return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
if (nBits != GetNextWorkRequired(pindexPrev))
@@ -1335,19 +1336,12 @@ bool CBlock::AcceptBlock()
if (!AddToBlockIndex(nFile, nBlockPos))
return error("AcceptBlock() : AddToBlockIndex failed");
// Don't relay old inventory during initial block download.
// Please keep this constant updated to a few thousand below current block count.
if (hashBestChain == hash && nBestHeight > 40000)
RelayInventory(CInv(MSG_BLOCK, hash));
// // Add atoms to user reviews for coins created
// vector<unsigned char> vchPubKey;
// if (ExtractPubKey(vtx[0].vout[0].scriptPubKey, false, vchPubKey))
// {
// unsigned short nAtom = GetRand(USHRT_MAX - 100) + 100;
// vector<unsigned short> vAtoms(1, nAtom);
// AddAtomsAndPropagate(Hash(vchPubKey.begin(), vchPubKey.end()), vAtoms, true);
// }
// Relay inventory, but don't relay old inventory during initial block download
if (hashBestChain == hash)
CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes)
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 55000))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
return true;
}
@@ -1556,8 +1550,8 @@ bool LoadBlockIndex(bool fAllowNew)
CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
CBigNum bnPubKey;
bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");
txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;
@@ -1720,6 +1714,7 @@ bool ProcessMessages(CNode* pfrom)
// (4) message start
// (12) command
// (4) size
// (4) checksum
// (x) data
//
@@ -1727,12 +1722,13 @@ bool ProcessMessages(CNode* pfrom)
{
// Scan for message start
CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
if (vRecv.end() - pstart < sizeof(CMessageHeader))
int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
if (vRecv.end() - pstart < nHeaderSize)
{
if (vRecv.size() > sizeof(CMessageHeader))
if (vRecv.size() > nHeaderSize)
{
printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
vRecv.erase(vRecv.begin(), vRecv.end() - sizeof(CMessageHeader));
vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
}
break;
}
@@ -1741,6 +1737,7 @@ bool ProcessMessages(CNode* pfrom)
vRecv.erase(vRecv.begin(), pstart);
// Read header
vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
CMessageHeader hdr;
vRecv >> hdr;
if (!hdr.IsValid())
@@ -1756,10 +1753,9 @@ bool ProcessMessages(CNode* pfrom)
{
// Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error
//if (fDebug)
// printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
if (fDebug)
printf("message-break\n");
vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
break;
}
@@ -1767,6 +1763,20 @@ bool ProcessMessages(CNode* pfrom)
CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
vRecv.ignore(nMessageSize);
// Checksum
if (vRecv.GetVersion() >= 209)
{
uint256 hash = Hash(vMsg.begin(), vMsg.end());
unsigned int nChecksum = 0;
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum)
{
printf("ProcessMessage(%s, %d bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
continue;
}
}
// Process message
bool fRet = false;
try
@@ -1843,6 +1853,9 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> strSubVer;
if (pfrom->nVersion >= 209 && !vRecv.empty())
vRecv >> pfrom->nStartingHeight;
if (pfrom->nVersion == 0)
return false;
@@ -1853,9 +1866,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true;
}
pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
if (pfrom->fClient)
{
@@ -1865,6 +1875,13 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
AddTimeData(pfrom->addr.ip, nTime);
// Change version
if (pfrom->nVersion >= 209)
pfrom->PushMessage("verack");
pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
if (pfrom->nVersion < 209)
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
// Ask the first connected node for block updates
static bool fAskedForBlocks;
if (!fAskedForBlocks && !pfrom->fClient)
@@ -1875,7 +1892,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
printf("version message: version %d\n", pfrom->nVersion);
printf("version message: version %d, blocks=%d\n", pfrom->nVersion, pfrom->nStartingHeight);
}
@@ -1886,6 +1903,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
else if (strCommand == "verack")
{
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
}
else if (strCommand == "addr")
{
vector<CAddress> vAddr;
@@ -2100,9 +2123,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> *pblock;
//// debug print
// printf("received block:\n");
// pblock->print();
printf("received block %s\n", pblock->GetHash().ToString().substr(0,16).c_str());
// pblock->print();
CInv inv(MSG_BLOCK, pblock->GetHash());
pfrom->AddInventoryKnown(inv);
@@ -2254,9 +2276,9 @@ bool SendMessages(CNode* pto)
// Delay tx inv messages to protect privacy,
// trickle them out to a few nodes at a time.
bool fSendTxInv = false;
if (GetTimeMillis() - pto->nLastSentTxInv > 1800 + GetRand(200))
if (GetTimeMillis() > pto->nNextSendTxInv)
{
pto->nLastSentTxInv = GetTimeMillis();
pto->nNextSendTxInv = GetTimeMillis() + 3000 + GetRand(2000);
fSendTxInv = true;
}
@@ -2387,8 +2409,11 @@ void GenerateBitcoins(bool fGenerate)
int nAddThreads = nProcessors - vnThreadsRunning[3];
printf("Starting %d BitcoinMiner threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
{
if (!CreateThread(ThreadBitcoinMiner, NULL))
printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
Sleep(10);
}
}
}
@@ -2991,7 +3016,7 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
if (nValue <= 0)
return _("Invalid amount");
if (nValue + nTransactionFee > GetBalance())
return _("You don't have enough money");
return _("Insufficient funds");
// Parse bitcoin address
CScript scriptPubKey;

6
main.h
View File

@@ -45,6 +45,8 @@ extern int64 nTransactionFee;
extern CAddress addrIncoming;
extern int fLimitProcessors;
extern int nLimitProcessors;
extern int fMinimizeToTray;
extern int fMinimizeOnClose;
@@ -1384,6 +1386,9 @@ public:
CPrivKey vchPrivKey;
int64 nTimeCreated;
int64 nTimeExpires;
string strComment;
//// todo: add something to note what created it (user, getnewaddress, change)
//// maybe should have a map<string, string> property map
CWalletKey(int64 nTimeExpiresIn=0)
{
@@ -1398,6 +1403,7 @@ public:
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
READWRITE(strComment);
)
};

View File

@@ -18,69 +18,59 @@ LIBPATHS= \
-L"/openssl/out" \
-L"/wxwidgets/lib/gcc_lib"
WXLIBS= \
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd
LIBS= \
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
-l db_cxx \
-l eay32 \
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd \
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
all: bitcoin.exe
headers.h.gch: headers.h $(HEADERS)
headers.h.gch: headers.h $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/util.o: util.cpp $(HEADERS)
obj/%.o: %.cpp $(HEADERS) headers.h.gch
g++ -c $(CFLAGS) -o $@ $<
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/main.o: main.cpp $(HEADERS) sha.h
g++ -c $(CFLAGS) -o $@ $<
obj/ui.o: ui.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/uibase.o: uibase.cpp uibase.h
g++ -c $(CFLAGS) -o $@ $<
obj/sha.o: sha.cpp sha.h
obj/sha.o: sha.cpp sha.h
g++ -c $(CFLAGS) -O3 -o $@ $<
obj/irc.o: irc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/rpc.o: rpc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/ui_res.o: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
OBJS= \
obj/util.o \
obj/script.o \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/main.o \
obj/rpc.o \
obj/init.o
bitcoin.exe: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o obj/ui_res.o
g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o \
obj/ui_res.o
obj/nogui/%.o: %.cpp $(HEADERS)
g++ -c $(CFLAGS) -DwxUSE_GUI=0 -o $@ $<
bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/sha.o obj/ui_res.o
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -l wxbase29ud $(LIBS)
bitcoin.exe: headers.h.gch $(OBJS)
-kill /f bitcoin.exe
g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
clean:
-del /Q obj\*
-del /Q obj\nogui\*
-del /Q headers.h.gch

65
makefile.osx Normal file
View File

@@ -0,0 +1,65 @@
# Copyright (c) 2009-2010 Satoshi Nakamoto
# Distributed under the MIT/X11 software license, see the accompanying
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
# Mac OS X makefile for bitcoin
# Laszlo Hanyecz (solar@heliacal.net)
DEPSDIR=/Users/macosuser/bitcoin/deps
INCLUDEPATHS= \
-I"$(DEPSDIR)/include"
LIBPATHS= \
-L"$(DEPSDIR)/lib"
WXLIBS=$(shell $(DEPSDIR)/bin/wx-config --libs --static)
LIBS= -dead_strip \
$(DEPSDIR)/lib/libdb_cxx-4.8.a \
$(DEPSDIR)/lib/libboost_system.a \
$(DEPSDIR)/lib/libboost_filesystem.a \
$(DEPSDIR)/lib/libcrypto.a
WXDEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -DNOPCH -DMSG_NOSIGNAL=0
DEBUGFLAGS=-g -DwxDEBUG_LEVEL=0
# ppc doesn't work because we don't support big-endian
CFLAGS=-mmacosx-version-min=10.5 -arch i386 -arch x86_64 -O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
all: bitcoin
obj/%.o: %.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/sha.o: sha.cpp sha.h
g++ -c $(CFLAGS) -O3 -o $@ $<
OBJS= \
obj/util.o \
obj/script.o \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/main.o \
obj/rpc.o \
obj/init.o
bitcoin: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
obj/nogui/%.o: %.cpp $(HEADERS)
g++ -c $(CFLAGS) -DwxUSE_GUI=0 -o $@ $<
bitcoind: $(OBJS:obj/%=obj/nogui/%) obj/sha.o
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
clean:
-rm -f obj/*.o
-rm -f obj/nogui/*.o

View File

@@ -13,66 +13,61 @@ LIBPATHS= \
-L"/usr/lib" \
-L"/usr/local/lib"
WXLIBS= \
-Wl,-Bstatic \
-l wx_gtk2ud-2.9 \
-Wl,-Bdynamic \
-l gtk-x11-2.0 -l SM
LIBS= \
-Wl,-Bstatic \
-l boost_system-mt -l boost_filesystem-mt \
-l db_cxx \
-l wx_gtk2ud-2.9 \
-Wl,-Bdynamic \
-l crypto \
-l gtk-x11-2.0 -l gthread-2.0 -l SM
-l gthread-2.0
WXDEFS=-D__WXGTK__ -DNOPCH
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
all: bitcoin
headers.h.gch: headers.h $(HEADERS)
headers.h.gch: headers.h $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/util.o: util.cpp $(HEADERS)
obj/%.o: %.cpp $(HEADERS) headers.h.gch
g++ -c $(CFLAGS) -o $@ $<
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/main.o: main.cpp $(HEADERS) sha.h
g++ -c $(CFLAGS) -o $@ $<
obj/ui.o: ui.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/uibase.o: uibase.cpp uibase.h
g++ -c $(CFLAGS) -o $@ $<
obj/sha.o: sha.cpp sha.h
obj/sha.o: sha.cpp sha.h
g++ -c $(CFLAGS) -O3 -o $@ $<
obj/irc.o: irc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
OBJS= \
obj/util.o \
obj/script.o \
obj/db.o \
obj/net.o \
obj/irc.o \
obj/main.o \
obj/rpc.o \
obj/init.o
obj/rpc.o: rpc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
bitcoin: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
obj/nogui/%.o: %.cpp $(HEADERS)
g++ -c $(CFLAGS) -DwxUSE_GUI=0 -o $@ $<
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o
bitcoind: $(OBJS:obj/%=obj/nogui/%) obj/sha.o
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -l wx_baseud-2.9 $(LIBS)
bitcoin: headers.h.gch $(OBJS)
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)
clean:
-rm obj/*
-rm obj/nogui/*
-rm headers.h.gch

View File

@@ -28,56 +28,79 @@ LIBS= \
WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
CFLAGS=/c /nologo /Ob0 /MDd /EHsc /GR /Zm300 $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h init.h sha.h
all: bitcoin.exe
obj\util.obj: util.cpp $(HEADERS)
.cpp{obj}.obj:
cl $(CFLAGS) /Fo$@ %s
obj\script.obj: script.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\util.obj: $(HEADERS)
obj\db.obj: db.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\script.obj: $(HEADERS)
obj\net.obj: net.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\db.obj: $(HEADERS)
obj\main.obj: main.cpp $(HEADERS) sha.h
cl $(CFLAGS) /Fo$@ %s
obj\net.obj: $(HEADERS)
obj\ui.obj: ui.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\irc.obj: $(HEADERS)
obj\uibase.obj: uibase.cpp uibase.h
cl $(CFLAGS) /Fo$@ %s
obj\main.obj: $(HEADERS)
obj\sha.obj: sha.cpp sha.h
obj\rpc.obj: $(HEADERS)
obj\init.obj: $(HEADERS)
obj\ui.obj: $(HEADERS)
obj\uibase.obj: $(HEADERS)
obj\sha.obj: sha.cpp sha.h
cl $(CFLAGS) /O2 /Fo$@ %s
obj\irc.obj: irc.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\rpc.obj: rpc.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\ui.res: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
OBJS= \
obj\util.obj \
obj\script.obj \
obj\db.obj \
obj\net.obj \
obj\irc.obj \
obj\main.obj \
obj\rpc.obj \
obj\init.obj
OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj \
obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\rpc.obj \
obj\ui.res
bitcoin.exe: $(OBJS)
-kill /f bitcoin.exe & sleep 1
bitcoin.exe: $(OBJS) obj\ui.obj obj\uibase.obj obj\sha.obj obj\ui.res
link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(LIBS)
.cpp{obj\nogui}.obj:
cl $(CFLAGS) /DwxUSE_GUI=0 /Fo$@ %s
obj\nogui\util.obj: $(HEADERS)
obj\nogui\script.obj: $(HEADERS)
obj\nogui\db.obj: $(HEADERS)
obj\nogui\net.obj: $(HEADERS)
obj\nogui\irc.obj: $(HEADERS)
obj\nogui\main.obj: $(HEADERS)
obj\nogui\rpc.obj: $(HEADERS)
obj\nogui\init.obj: $(HEADERS)
bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\sha.obj obj\ui.res
link /nologo /DEBUG /OUT:$@ $(LIBPATHS) $** $(LIBS)
clean:
-del /Q obj\*
-del *.ilk

View File

@@ -927,9 +927,7 @@ void ThreadOpenConnections2(void* parg)
continue;
// Only try the old stuff if we don't have enough connections
if (vNodes.size() >= 2 && nSinceLastSeen > 7 * 24 * 60 * 60)
continue;
if (vNodes.size() >= 5 && nSinceLastSeen > 24 * 60 * 60)
if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
continue;
// If multiple addresses are ready, prioritize by time since

65
net.h
View File

@@ -8,6 +8,7 @@ class CInv;
class CRequestTracker;
class CNode;
class CBlockIndex;
extern int nBestHeight;
@@ -45,6 +46,7 @@ bool StopNode();
// (4) message start
// (12) command
// (4) size
// (4) checksum
// The message start string is designed to be unlikely to occur in normal data.
// The characters are rarely used upper ascii, not valid as UTF-8, and produce
@@ -58,6 +60,7 @@ public:
char pchMessageStart[sizeof(::pchMessageStart)];
char pchCommand[COMMAND_SIZE];
unsigned int nMessageSize;
unsigned int nChecksum;
CMessageHeader()
{
@@ -65,6 +68,7 @@ public:
memset(pchCommand, 0, sizeof(pchCommand));
pchCommand[1] = 1;
nMessageSize = -1;
nChecksum = 0;
}
CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
@@ -72,6 +76,7 @@ public:
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn;
nChecksum = 0;
}
IMPLEMENT_SERIALIZE
@@ -79,6 +84,8 @@ public:
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(nMessageSize);
if (nVersion >= 209)
READWRITE(nChecksum);
)
string GetCommand()
@@ -470,6 +477,7 @@ extern CAddress addrProxy;
class CNode
{
public:
@@ -484,7 +492,8 @@ public:
int64 nLastRecv;
int64 nLastSendEmpty;
int64 nTimeConnected;
unsigned int nPushPos;
unsigned int nHeaderStart;
unsigned int nMessageStart;
CAddress addr;
int nVersion;
bool fClient;
@@ -501,6 +510,7 @@ public:
uint256 hashContinue;
CBlockIndex* pindexLastGetBlocksBegin;
uint256 hashLastGetBlocksEnd;
int nStartingHeight;
// flood
vector<CAddress> vAddrToSend;
@@ -512,7 +522,7 @@ public:
vector<CInv> vInventoryToSend;
CCriticalSection cs_inventory;
multimap<int64, CInv> mapAskFor;
int64 nLastSentTxInv;
int64 nNextSendTxInv;
// publish and subscription
vector<char> vfSubscribe;
@@ -523,12 +533,15 @@ public:
nServices = 0;
hSocket = hSocketIn;
vSend.SetType(SER_NETWORK);
vSend.SetVersion(0);
vRecv.SetType(SER_NETWORK);
vRecv.SetVersion(0);
nLastSend = 0;
nLastRecv = 0;
nLastSendEmpty = GetTime();
nTimeConnected = GetTime();
nPushPos = -1;
nHeaderStart = -1;
nMessageStart = -1;
addr = addrIn;
nVersion = 0;
fClient = false; // set by version message
@@ -541,7 +554,9 @@ public:
hashContinue = 0;
pindexLastGetBlocksBegin = 0;
hashLastGetBlocksEnd = 0;
nStartingHeight = -1;
fGetAddr = false;
nNextSendTxInv = 0;
vfSubscribe.assign(256, false);
// Push a version message
@@ -550,7 +565,8 @@ public:
CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, string(pszSubVer));
PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, string(pszSubVer), nBestHeight);
}
~CNode()
@@ -639,10 +655,11 @@ public:
void BeginMessage(const char* pszCommand)
{
cs_vSend.Enter();
if (nPushPos != -1)
if (nHeaderStart != -1)
AbortMessage();
nPushPos = vSend.size();
nHeaderStart = vSend.size();
vSend << CMessageHeader(pszCommand, 0);
nMessageStart = vSend.size();
if (fDebug)
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("sending: %s ", pszCommand);
@@ -650,10 +667,11 @@ public:
void AbortMessage()
{
if (nPushPos == -1)
if (nHeaderStart == -1)
return;
vSend.resize(nPushPos);
nPushPos = -1;
vSend.resize(nHeaderStart);
nHeaderStart = -1;
nMessageStart = -1;
cs_vSend.Leave();
printf("(aborted)\n");
}
@@ -667,25 +685,36 @@ public:
return;
}
if (nPushPos == -1)
if (nHeaderStart == -1)
return;
// Patch in the size
unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
// Set the size
unsigned int nSize = vSend.size() - nMessageStart;
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
// Set the checksum
if (vSend.GetVersion() >= 209)
{
uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
unsigned int nChecksum = 0;
memcpy(&nChecksum, &hash, sizeof(nChecksum));
assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
}
printf("(%d bytes) ", nSize);
printf("\n");
nPushPos = -1;
nHeaderStart = -1;
nMessageStart = -1;
cs_vSend.Leave();
}
void EndMessageAbortIfEmpty()
{
if (nPushPos == -1)
if (nHeaderStart == -1)
return;
int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
int nSize = vSend.size() - nMessageStart;
if (nSize > 0)
EndMessage();
else
@@ -694,9 +723,9 @@ public:
const char* GetMessageCommand() const
{
if (nPushPos == -1)
if (nHeaderStart == -1)
return "";
return &vSend[nPushPos] + offsetof(CMessageHeader, pchCommand);
return &vSend[nHeaderStart] + offsetof(CMessageHeader, pchCommand);
}

426
rpc.cpp
View File

@@ -26,7 +26,7 @@ void ThreadRPCServer2(void* parg);
///
/// Note: I'm not finished designing this interface, it's still subject to change.
/// Note: This interface may still be subject to change.
///
@@ -66,6 +66,29 @@ Value getblocknumber(const Array& params)
}
Value getconnectioncount(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getconnectioncount (no parameters)\n"
"Returns the number of connections to other nodes.");
return (int)vNodes.size();
}
double GetDifficulty()
{
// Floating point number that is a multiple of the minimum difficulty,
// minimum difficulty = 1.0.
if (pindexBest == NULL)
return 1.0;
int nShift = 256 - 32 - 31; // to fit in a uint
double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint();
double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint();
return dMinimum / dCurrently;
}
Value getdifficulty(const Array& params)
{
if (params.size() != 0)
@@ -73,15 +96,73 @@ Value getdifficulty(const Array& params)
"getdifficulty (no parameters)\n"
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
if (pindexBest == NULL)
throw runtime_error("block chain not loaded");
return GetDifficulty();
}
// Floating point number that is a multiple of the minimum difficulty,
// minimum difficulty = 1.0.
int nShift = 256 - 32 - 31; // to fit in a uint
double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint();
double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint();
return dMinimum / dCurrently;
Value getbalance(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getbalance (no parameters)\n"
"Returns the server's available balance.");
return ((double)GetBalance() / (double)COIN);
}
Value getgenerate(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getgenerate (no parameters)\n"
"Returns true or false.");
return (bool)fGenerateBitcoins;
}
Value setgenerate(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"setgenerate <generate> [genproclimit]\n"
"<generate> is true or false to turn generation on or off.\n"
"Generation is limited to [genproclimit] processors, -1 is unlimited.");
bool fGenerate = true;
if (params.size() > 0)
fGenerate = params[0].get_bool();
if (params.size() > 1)
{
int nGenProcLimit = params[1].get_int();
fLimitProcessors = (nGenProcLimit != -1);
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
if (nGenProcLimit != -1)
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
}
GenerateBitcoins(fGenerate);
return Value::null;
}
Value getinfo(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getinfo (no parameters)");
Object obj;
obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
obj.push_back(Pair("blocks", (int)nBestHeight + 1));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
return obj;
}
@@ -102,12 +183,78 @@ Value getnewaddress(const Array& params)
// Generate a new key that is added to wallet
string strAddress = PubKeyToAddress(GenerateNewKey());
if (params.size() > 0)
SetAddressBookName(strAddress, strLabel);
SetAddressBookName(strAddress, strLabel);
return strAddress;
}
Value setlabel(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"setlabel <bitcoinaddress> <label>\n"
"Sets the label associated with the given address.");
string strAddress = params[0].get_str();
string strLabel;
if (params.size() > 1)
strLabel = params[1].get_str();
SetAddressBookName(strAddress, strLabel);
return Value::null;
}
Value getlabel(const Array& params)
{
if (params.size() != 1)
throw runtime_error(
"getlabel <bitcoinaddress>\n"
"Returns the label associated with the given address.");
string strAddress = params[0].get_str();
string strLabel;
CRITICAL_BLOCK(cs_mapAddressBook)
{
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
if (mi != mapAddressBook.end() && !(*mi).second.empty())
strLabel = (*mi).second;
}
return strLabel;
}
Value getaddressesbylabel(const Array& params)
{
if (params.size() != 1)
throw runtime_error(
"getaddressesbylabel <label>\n"
"Returns the list of addresses with the given label.");
string strLabel = params[0].get_str();
// Find all addresses that have the given label
Array ret;
CRITICAL_BLOCK(cs_mapAddressBook)
{
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
{
const string& strAddress = item.first;
const string& strName = item.second;
if (strName == strLabel)
{
// We're only adding valid bitcoin addresses and not ip addresses
CScript scriptPubKey;
if (scriptPubKey.SetBitcoinAddress(strAddress))
ret.push_back(strAddress);
}
}
}
return ret;
}
Value sendtoaddress(const Array& params)
{
if (params.size() < 2 || params.size() > 4)
@@ -157,11 +304,11 @@ Value listtransactions(const Array& params)
}
Value getamountreceived(const Array& params)
Value getreceivedbyaddress(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"getamountreceived <bitcoinaddress> [minconf=1]\n"
"getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
// Bitcoin address
@@ -169,6 +316,8 @@ Value getamountreceived(const Array& params)
CScript scriptPubKey;
if (!scriptPubKey.SetBitcoinAddress(strAddress))
throw runtime_error("Invalid bitcoin address");
if (!IsMine(scriptPubKey))
return (double)0.0;
// Minimum confirmations
int nMinDepth = 1;
@@ -196,6 +345,59 @@ Value getamountreceived(const Array& params)
}
Value getreceivedbylabel(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"getreceivedbylabel <label> [minconf=1]\n"
"Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.");
// Get the set of pub keys that have the label
string strLabel = params[0].get_str();
set<CScript> setPubKey;
CRITICAL_BLOCK(cs_mapAddressBook)
{
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
{
const string& strAddress = item.first;
const string& strName = item.second;
if (strName == strLabel)
{
// We're only counting our own valid bitcoin addresses and not ip addresses
CScript scriptPubKey;
if (scriptPubKey.SetBitcoinAddress(strAddress))
if (IsMine(scriptPubKey))
setPubKey.insert(scriptPubKey);
}
}
}
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 1)
nMinDepth = params[1].get_int();
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
foreach(const CTxOut& txout, wtx.vout)
if (setPubKey.count(txout.scriptPubKey))
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
}
return (double)nAmount / (double)COIN;
}
struct tallyitem
{
int64 nAmount;
@@ -207,23 +409,18 @@ struct tallyitem
}
};
Value getallreceived(const Array& params)
Value ListReceived(const Array& params, bool fByLabels)
{
if (params.size() > 1)
throw runtime_error(
"getallreceived [minconf=1]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n"
"Returns an array of objects containing:\n"
" \"address\" : bitcoin address\n"
" \"amount\" : total amount received by the address\n"
" \"conf\" : number of confirmations\n"
" \"label\" : the label set for this address when it was created by getnewaddress");
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 0)
nMinDepth = params[0].get_int();
// Whether to include empty accounts
bool fIncludeEmpty = false;
if (params.size() > 1)
fIncludeEmpty = params[1].get_bool();
// Tally
map<uint160, tallyitem> mapTally;
CRITICAL_BLOCK(cs_mapWallet)
@@ -235,45 +432,119 @@ Value getallreceived(const Array& params)
continue;
int nDepth = wtx.GetDepthInMainChain();
if (nDepth >= nMinDepth)
{
foreach(const CTxOut& txout, wtx.vout)
{
uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
if (hash160 == 0 || !mapPubKeys.count(hash160))
continue;
if (nDepth < nMinDepth)
continue;
tallyitem& item = mapTally[hash160];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
}
foreach(const CTxOut& txout, wtx.vout)
{
// Only counting our own bitcoin addresses and not ip addresses
uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine
continue;
tallyitem& item = mapTally[hash160];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
}
}
}
// Reply
Array ret;
map<string, tallyitem> mapLabelTally;
CRITICAL_BLOCK(cs_mapAddressBook)
{
for (map<uint160, tallyitem>::iterator it = mapTally.begin(); it != mapTally.end(); ++it)
foreach(const PAIRTYPE(string, string)& item, mapAddressBook)
{
string strAddress = Hash160ToAddress((*it).first);
string strLabel;
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
if (mi != mapAddressBook.end())
strLabel = (*mi).second;
const string& strAddress = item.first;
const string& strLabel = item.second;
uint160 hash160;
if (!AddressToHash160(strAddress, hash160))
continue;
map<uint160, tallyitem>::iterator it = mapTally.find(hash160);
if (it == mapTally.end() && !fIncludeEmpty)
continue;
int64 nAmount = 0;
int nConf = INT_MAX;
if (it != mapTally.end())
{
nAmount = (*it).second.nAmount;
nConf = (*it).second.nConf;
}
if (fByLabels)
{
tallyitem& item = mapLabelTally[strLabel];
item.nAmount += nAmount;
item.nConf = min(item.nConf, nConf);
}
else
{
Object obj;
obj.push_back(Pair("address", strAddress));
obj.push_back(Pair("label", strLabel));
obj.push_back(Pair("amount", (double)nAmount / (double)COIN));
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
ret.push_back(obj);
}
}
}
if (fByLabels)
{
for (map<string, tallyitem>::iterator it = mapLabelTally.begin(); it != mapLabelTally.end(); ++it)
{
int64 nAmount = (*it).second.nAmount;
int nConf = (*it).second.nConf;
Object obj;
obj.push_back(Pair("address", strAddress));
obj.push_back(Pair("amount", (double)(*it).second.nAmount / (double)COIN));
obj.push_back(Pair("conf", (*it).second.nConf));
obj.push_back(Pair("label", strLabel));
obj.push_back(Pair("label", (*it).first));
obj.push_back(Pair("amount", (double)nAmount / (double)COIN));
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
ret.push_back(obj);
}
}
return ret;
}
Value listreceivedbyaddress(const Array& params)
{
if (params.size() > 2)
throw runtime_error(
"listreceivedbyaddress [minconf=1] [includeempty=false]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n"
"[includeempty] whether to include addresses that haven't received any payments.\n"
"Returns an array of objects containing:\n"
" \"address\" : receiving address\n"
" \"label\" : the label of the receiving address\n"
" \"amount\" : total amount received by the address\n"
" \"confirmations\" : number of confirmations of the most recent transaction included");
return ListReceived(params, false);
}
Value listreceivedbylabel(const Array& params)
{
if (params.size() > 2)
throw runtime_error(
"listreceivedbylabel [minconf=1] [includeempty=false]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n"
"[includeempty] whether to include labels that haven't received any payments.\n"
"Returns an array of objects containing:\n"
" \"label\" : the label of the receiving addresses\n"
" \"amount\" : total amount received by addresses with this label\n"
" \"confirmations\" : number of confirmations of the most recent transaction included");
return ListReceived(params, true);
}
@@ -287,15 +558,27 @@ Value getallreceived(const Array& params)
typedef Value(*rpcfn_type)(const Array& params);
pair<string, rpcfn_type> pCallTable[] =
{
make_pair("stop", &stop),
make_pair("getblockcount", &getblockcount),
make_pair("getblocknumber", &getblocknumber),
make_pair("getdifficulty", &getdifficulty),
make_pair("getnewaddress", &getnewaddress),
make_pair("sendtoaddress", &sendtoaddress),
make_pair("listtransactions", &listtransactions),
make_pair("getamountreceived", &getamountreceived),
make_pair("getallreceived", &getallreceived),
make_pair("stop", &stop),
make_pair("getblockcount", &getblockcount),
make_pair("getblocknumber", &getblocknumber),
make_pair("getconnectioncount", &getconnectioncount),
make_pair("getdifficulty", &getdifficulty),
make_pair("getbalance", &getbalance),
make_pair("getgenerate", &getgenerate),
make_pair("setgenerate", &setgenerate),
make_pair("getinfo", &getinfo),
make_pair("getnewaddress", &getnewaddress),
make_pair("setlabel", &setlabel),
make_pair("getlabel", &getlabel),
make_pair("getaddressesbylabel", &getaddressesbylabel),
make_pair("sendtoaddress", &sendtoaddress),
make_pair("listtransactions", &listtransactions),
make_pair("getamountreceived", &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
make_pair("getallreceived", &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
make_pair("getreceivedbyaddress", &getreceivedbyaddress),
make_pair("getreceivedbylabel", &getreceivedbylabel),
make_pair("listreceivedbyaddress", &listreceivedbyaddress),
make_pair("listreceivedbylabel", &listreceivedbylabel),
};
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
@@ -568,14 +851,25 @@ int CommandLineRPC(int argc, char *argv[])
Array params;
for (int i = 2; i < argc; i++)
params.push_back(argv[i]);
// Special case other types
int n = params.size();
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]);
//
// Special case other types
//
if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getreceivedbylabel" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
if (strMethod == "getallreceived" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo<bool>(params[1]);
// Execute
Value result = CallRPC(strMethod, params);
@@ -584,18 +878,18 @@ int CommandLineRPC(int argc, char *argv[])
string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true));
if (result.type() != null_type)
{
if (fWindows)
if (fWindows && fGUI)
// Windows GUI apps can't print to command line,
// so for now settle for a message box yuck
wxMessageBox(strResult.c_str(), "Bitcoin", wxOK);
// so settle for a message box yuck
MyMessageBox(strResult.c_str(), "Bitcoin", wxOK);
else
fprintf(stdout, "%s\n", strResult.c_str());
}
return 0;
}
catch (std::exception& e) {
if (fWindows)
wxMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
if (fWindows && fGUI)
MyMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
else
fprintf(stderr, "error: %s\n", e.what());
} catch (...) {

View File

@@ -19,7 +19,7 @@ class CScript;
class CDataStream;
class CAutoFile;
static const int VERSION = 205;
static const int VERSION = 209;
static const char* pszSubVer = ".0";
@@ -809,6 +809,18 @@ public:
vch.insert(it, first, last);
}
void insert(iterator it, vector<char>::const_iterator first, vector<char>::const_iterator last)
{
if (it == vch.begin() + nReadPos && last - first <= nReadPos)
{
// special case for inserting at the front when there's room
nReadPos -= (last - first);
memcpy(&vch[nReadPos], &first[0], last - first);
}
else
vch.insert(it, first, last);
}
#if !defined(_MSC_VER) || _MSC_VER >= 1300
void insert(iterator it, const char* first, const char* last)
{

639
ui.cpp
View File

@@ -7,21 +7,15 @@
#include <crtdbg.h>
#endif
bool GetStartOnSystemStartup();
void SetStartOnSystemStartup(bool fAutoStart);
DEFINE_EVENT_TYPE(wxEVT_UITHREADCALL)
CMainFrame* pframeMain = NULL;
CMyTaskBarIcon* ptaskbaricon = NULL;
extern int g_isPainting;
bool fClosedToTray = false;
// Settings
int fMinimizeToTray = true;
int fMinimizeOnClose = true;
@@ -34,47 +28,6 @@ int fMinimizeOnClose = true;
// Util
//
void ExitTimeout(void* parg)
{
#ifdef __WXMSW__
Sleep(5000);
ExitProcess(0);
#endif
}
void Shutdown(void* parg)
{
static CCriticalSection cs_Shutdown;
static bool fTaken;
bool fFirstThread;
CRITICAL_BLOCK(cs_Shutdown)
{
fFirstThread = !fTaken;
fTaken = true;
}
static bool fExit;
if (fFirstThread)
{
fShutdown = true;
nTransactionsUpdated++;
DBFlush(false);
StopNode();
DBFlush(true);
CreateThread(ExitTimeout, NULL);
Sleep(50);
printf("Bitcoin exiting\n\n");
fExit = true;
exit(0);
}
else
{
while (!fExit)
Sleep(500);
Sleep(100);
ExitThread(0);
}
}
void HandleCtrlA(wxKeyEvent& event)
{
// Ctrl-a select all
@@ -209,16 +162,10 @@ void CalledMessageBox(const string& message, const string& caption, int style, w
int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
{
if (fDaemon)
{
printf("wxMessageBox %s: %s\n", caption.c_str(), message.c_str());
return wxOK;
}
#ifdef __WXMSW__
return wxMessageBox(message, caption, style, parent, x, y);
#else
if (wxThread::IsMain())
if (wxThread::IsMain() || fDaemon)
{
return wxMessageBox(message, caption, style, parent, x, y);
}
@@ -246,6 +193,12 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* pa
return (ThreadSafeMessageBox(strMessage, strCaption, wxYES_NO, parent) == wxYES);
}
void CalledSetStatusBar(const string& strText, int nField)
{
if (pframeMain && pframeMain->m_statusBar)
pframeMain->m_statusBar->SetStatusText(strText, nField);
}
void SetDefaultReceivingAddress(const string& strAddress)
{
// Update main window address and database
@@ -304,16 +257,26 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
m_staticTextBalance->SetSize(140, 17);
// resize to fit ubuntu's huge default font
dResize = 1.22;
SetSize(dResize * GetSize().GetWidth(), 1.09 * GetSize().GetHeight());
SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
#endif
m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
m_listCtrl->SetFocus();
ptaskbaricon = new CMyTaskBarIcon();
#ifdef __WXMAC__
// Mac automatically moves wxID_EXIT, wxID_PREFERENCES and wxID_ABOUT
// to their standard places, leaving these menus empty.
GetMenuBar()->Remove(2); // remove Help menu
GetMenuBar()->Remove(0); // remove File menu
#endif
// Init column headers
int nDateWidth = DateTimeStr(1229413914).size() * 6 + 8;
if (!strstr(DateTimeStr(1229413914).c_str(), "2008"))
nDateWidth += 12;
#ifdef __WXMAC__
nDateWidth += 5;
dResize -= 0.01;
#endif
wxListCtrl* pplistCtrl[] = {m_listCtrlAll, m_listCtrlSentReceived, m_listCtrlSent, m_listCtrlReceived};
foreach(wxListCtrl* p, pplistCtrl)
{
@@ -327,7 +290,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
}
// Init status bar
int pnWidths[3] = { -100, 88, 290 };
int pnWidths[3] = { -100, 88, 300 };
#ifndef __WXMSW__
pnWidths[1] = pnWidths[1] * 1.1 * dResize;
pnWidths[2] = pnWidths[2] * 1.1 * dResize;
@@ -563,7 +526,7 @@ string SingleLine(const string& strIn)
bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
int64 nCredit = wtx.GetCredit();
int64 nCredit = wtx.GetCredit(true);
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
uint256 hash = wtx.GetHash();
@@ -1622,7 +1585,6 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
//////////////////////////////////////////////////////////////////////////////
//
// CAboutDialog
@@ -2006,7 +1968,7 @@ void CSendingDialog::StartTransfer()
// Make sure we have enough money
if (nPrice + nTransactionFee > GetBalance())
{
Error(_("You don't have enough money"));
Error(_("Insufficient funds"));
return;
}
@@ -2073,7 +2035,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
return;
if (nPrice + nTransactionFee > GetBalance())
{
Error(_("You don't have enough money"));
Error(_("Insufficient funds"));
return;
}
CKey key;
@@ -2211,7 +2173,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
wxListCtrl* plistCtrl = fMine ? m_listCtrlReceiving : m_listCtrlSending;
int nIndex = InsertLine(plistCtrl, strName, strAddress);
if (strAddress == (fMine ? strDefaultReceiving : strInitSelected))
if (strAddress == (fMine ? strDefaultReceiving : string(strInitSelected)))
plistCtrl->SetItemState(nIndex, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
}
}
@@ -2498,7 +2460,7 @@ void CMyTaskBarIcon::OnMenuRestore(wxCommandEvent& event)
void CMyTaskBarIcon::OnMenuOptions(wxCommandEvent& event)
{
// Since it's modal, get the main window to do it
wxCommandEvent event2(wxEVT_COMMAND_MENU_SELECTED, wxID_MENUOPTIONSOPTIONS);
wxCommandEvent event2(wxEVT_COMMAND_MENU_SELECTED, wxID_PREFERENCES);
pframeMain->GetEventHandler()->AddPendingEvent(event2);
}
@@ -2554,553 +2516,26 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu()
//////////////////////////////////////////////////////////////////////////////
//
// CMyApp
//
// Define a new application
class CMyApp: public wxApp
void CreateMainWindow()
{
public:
wxLocale m_locale;
CMyApp(){};
~CMyApp(){};
bool OnInit();
bool OnInit2();
int OnExit();
// 2nd-level exception handling: we get all the exceptions occurring in any
// event handler here
virtual bool OnExceptionInMainLoop();
// 3rd, and final, level exception handling: whenever an unhandled
// exception is caught, this function is called
virtual void OnUnhandledException();
// and now for something different: this function is called in case of a
// crash (e.g. dereferencing null pointer, division by 0, ...)
virtual void OnFatalException();
};
IMPLEMENT_APP(CMyApp)
bool CMyApp::OnInit()
{
bool fRet = false;
try
{
fRet = OnInit2();
}
catch (std::exception& e) {
PrintException(&e, "OnInit()");
} catch (...) {
PrintException(NULL, "OnInit()");
}
if (!fRet)
Shutdown(NULL);
return fRet;
}
bool CMyApp::OnInit2()
{
#ifdef _MSC_VER
// Turn off microsoft heap dump noise
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif
#if defined(__WXMSW__) && defined(__WXDEBUG__)
// Disable malfunctioning wxWidgets debug assertion
g_isPainting = 10000;
#endif
wxImage::AddHandler(new wxPNGHandler);
#ifdef __WXMSW__
SetAppName("Bitcoin");
#else
SetAppName("bitcoin");
umask(077);
#endif
#ifdef __WXMSW__
#if wxUSE_UNICODE
// Hack to set wxConvLibc codepage to UTF-8 on Windows,
// may break if wxMBConv_win32 implementation in strconv.cpp changes.
class wxMBConv_win32 : public wxMBConv
{
public:
long m_CodePage;
size_t m_minMBCharWidth;
};
if (((wxMBConv_win32*)&wxConvLibc)->m_CodePage == CP_ACP)
((wxMBConv_win32*)&wxConvLibc)->m_CodePage = CP_UTF8;
#endif
#endif
// Load locale/<lang>/LC_MESSAGES/bitcoin.mo language file
m_locale.Init(wxLANGUAGE_DEFAULT, 0);
m_locale.AddCatalogLookupPathPrefix("locale");
if (!fWindows)
{
m_locale.AddCatalogLookupPathPrefix("/usr/share/locale");
m_locale.AddCatalogLookupPathPrefix("/usr/local/share/locale");
}
m_locale.AddCatalog("wxstd"); // wxWidgets standard translations, if any
m_locale.AddCatalog("bitcoin");
//
// Parameters
//
if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '/')
{
int ret = CommandLineRPC(argc, argv);
exit(ret);
}
ParseParameters(argc, argv);
if (mapArgs.count("-?") || mapArgs.count("--help"))
{
wxString strUsage = string() +
_("Usage: bitcoin [options]") + "\t\t\t\t\t\t\n" +
_("Options:\n") +
" -gen \t\t " + _("Generate coins\n") +
" -gen=0 \t\t " + _("Don't generate coins\n") +
" -min \t\t " + _("Start minimized\n") +
" -datadir=<dir> \t " + _("Specify data directory\n") +
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
" -connect=<ip> \t " + _("Connect only to the specified node\n") +
" -? \t\t " + _("This help message\n");
if (fWindows)
{
// Remove spaces, the tabs make the columns line up in the message box
for (int i = 0; i < 50; i++)
strUsage.Replace(" \t", "\t");
wxMessageBox(strUsage, "Bitcoin", wxOK);
}
else
{
// Remove tabs
strUsage.Replace("\t", "");
fprintf(stderr, "%s", ((string)strUsage).c_str());
}
return false;
}
if (mapArgs.count("-datadir"))
strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
if (mapArgs.count("-debug"))
fDebug = true;
if (mapArgs.count("-printtodebugger"))
fPrintToDebugger = true;
if (mapArgs.count("-daemon") || mapArgs.count("-d"))
{
fDaemon = true;
/// todo: need to fork
/// should it fork after the bind/single instance stuff?
}
if (!fDebug && !pszSetDataDir[0])
ShrinkDebugFile();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Bitcoin version 0.%d.%d%s beta, OS version %s\n", VERSION/100, VERSION%100, pszSubVer, ((string)wxGetOsDescription()).c_str());
printf("System default language is %d %s\n", m_locale.GetSystemLanguage(), ((string)m_locale.GetSysName()).c_str());
printf("Language file %s (%s)\n", (string("locale/") + (string)m_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)m_locale.GetLocale()).c_str());
if (mapArgs.count("-loadblockindextest"))
{
CTxDB txdb("r");
txdb.LoadBlockIndex();
PrintBlockTree();
return false;
}
//
// Limit to single instance per user
// Required to protect the database files if we're going to keep deleting log.*
//
#ifdef __WXMSW__
// todo: wxSingleInstanceChecker wasn't working on Linux, never deleted its lock file
// maybe should go by whether successfully bind port 8333 instead
wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
for (int i = 0; i < strMutexName.size(); i++)
if (!isalnum(strMutexName[i]))
strMutexName[i] = '.';
wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
if (psingleinstancechecker->IsAnotherRunning())
{
printf("Existing instance found\n");
unsigned int nStart = GetTime();
loop
{
// TODO: find out how to do this in Linux, or replace with wxWidgets commands
// Show the previous instance and exit
HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
if (hwndPrev)
{
if (IsIconic(hwndPrev))
ShowWindow(hwndPrev, SW_RESTORE);
SetForegroundWindow(hwndPrev);
return false;
}
if (GetTime() > nStart + 60)
return false;
// Resume this instance if the other exits
delete psingleinstancechecker;
Sleep(1000);
psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
if (!psingleinstancechecker->IsAnotherRunning())
break;
}
}
#endif
// Bind to the port early so we can tell if another instance is already running.
// This is a backup to wxSingleInstanceChecker, which doesn't work on Linux.
string strErrors;
if (!BindListenPort(strErrors))
{
wxMessageBox(strErrors, "Bitcoin");
return false;
}
//
// Load data files
//
bool fFirstRun;
strErrors = "";
int64 nStart;
printf("Loading addresses...\n");
nStart = GetTimeMillis();
if (!LoadAddresses())
strErrors += _("Error loading addr.dat \n");
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading block index...\n");
nStart = GetTimeMillis();
if (!LoadBlockIndex())
strErrors += _("Error loading blkindex.dat \n");
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Loading wallet...\n");
nStart = GetTimeMillis();
if (!LoadWallet(fFirstRun))
strErrors += _("Error loading wallet.dat \n");
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
printf("Done loading\n");
//// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
printf("mapKeys.size() = %d\n", mapKeys.size());
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
printf("mapWallet.size() = %d\n", mapWallet.size());
printf("mapAddressBook.size() = %d\n", mapAddressBook.size());
if (!strErrors.empty())
{
wxMessageBox(strErrors, "Bitcoin");
return false;
}
// Add wallet transactions that aren't already in a block to mapTransactions
ReacceptWalletTransactions();
//
// Parameters
//
if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
{
PrintBlockTree();
return false;
}
if (mapArgs.count("-printblock"))
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
block.ReadFromDisk(pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
nFound++;
}
}
if (nFound == 0)
printf("No blocks matching %s were found\n", strMatch.c_str());
return false;
}
if (mapArgs.count("-gen"))
{
if (mapArgs["-gen"].empty())
fGenerateBitcoins = true;
else
fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0);
}
if (mapArgs.count("-proxy"))
{
fUseProxy = true;
addrProxy = CAddress(mapArgs["-proxy"]);
if (!addrProxy.IsValid())
{
wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
return false;
}
}
if (mapArgs.count("-addnode"))
{
foreach(string strAddr, mapMultiArgs["-addnode"])
{
CAddress addr(strAddr, NODE_NETWORK);
addr.nTime = 0; // so it won't relay unless successfully connected
if (addr.IsValid())
AddAddress(addr);
}
}
//
// Create the main frame window
//
if (!fDaemon)
{
pframeMain = new CMainFrame(NULL);
if (mapArgs.count("-min"))
pframeMain->Iconize(true);
pframeMain->Show(true); // have to show first to get taskbar button to hide
if (fMinimizeToTray && pframeMain->IsIconized())
fClosedToTray = true;
pframeMain->Show(!fClosedToTray);
ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
CreateThread(ThreadDelayedRepaint, NULL);
}
if (!CheckDiskSpace())
return false;
RandAddSeedPerfmon();
if (!CreateThread(StartNode, NULL))
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
if (mapArgs.count("-server") || fDaemon)
CreateThread(ThreadRPCServer, NULL);
if (fFirstRun)
SetStartOnSystemStartup(true);
//
// Tests
//
#ifdef __WXMSW__
if (argc >= 2 && stricmp(argv[1], "-send") == 0)
#else
if (argc >= 2 && strcmp(argv[1], "-send") == 0)
#endif
{
int64 nValue = 1;
if (argc >= 3)
ParseMoney(argv[2], nValue);
string strAddress;
if (argc >= 4)
strAddress = argv[3];
CAddress addr(strAddress);
CWalletTx wtx;
wtx.mapValue["to"] = strAddress;
wtx.mapValue["from"] = addrLocalHost.ToString();
wtx.mapValue["message"] = "command line send";
// Send to IP address
CSendingDialog* pdialog = new CSendingDialog(pframeMain, addr, nValue, wtx);
if (!pdialog->ShowModal())
return false;
}
return true;
}
int CMyApp::OnExit()
{
Shutdown(NULL);
return wxApp::OnExit();
}
bool CMyApp::OnExceptionInMainLoop()
{
try
{
throw;
}
catch (std::exception& e)
{
PrintException(&e, "CMyApp::OnExceptionInMainLoop()");
wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
Sleep(1000);
throw;
}
catch (...)
{
PrintException(NULL, "CMyApp::OnExceptionInMainLoop()");
wxLogWarning("Unknown exception");
Sleep(1000);
throw;
}
return true;
}
void CMyApp::OnUnhandledException()
{
// this shows how we may let some exception propagate uncaught
try
{
throw;
}
catch (std::exception& e)
{
PrintException(&e, "CMyApp::OnUnhandledException()");
wxLogWarning("Exception %s %s", typeid(e).name(), e.what());
Sleep(1000);
throw;
}
catch (...)
{
PrintException(NULL, "CMyApp::OnUnhandledException()");
wxLogWarning("Unknown exception");
Sleep(1000);
throw;
}
}
void CMyApp::OnFatalException()
{
wxMessageBox(_("Program has crashed and will terminate. "), "Bitcoin", wxOK | wxICON_ERROR);
pframeMain = new CMainFrame(NULL);
if (mapArgs.count("-min"))
pframeMain->Iconize(true);
pframeMain->Show(true); // have to show first to get taskbar button to hide
if (fMinimizeToTray && pframeMain->IsIconized())
fClosedToTray = true;
pframeMain->Show(!fClosedToTray);
ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
CreateThread(ThreadDelayedRepaint, NULL);
}
#ifdef __WXMSW__
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 = LoadLibraryA("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()
{
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
}
bool GetStartOnSystemStartup()
{
return wxFileExists(StartupShortcutPath());
}
void SetStartOnSystemStartup(bool fAutoStart)
{
// If the shortcut exists already, remove it for updating
remove(StartupShortcutPath().c_str());
if (fAutoStart)
{
CoInitialize(NULL);
// Get a pointer to the IShellLink interface.
IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**>(&psl));
if (SUCCEEDED(hres))
{
// Get the current executable path
TCHAR pszExePath[MAX_PATH];
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
// Set the path to the shortcut target
psl->SetPath(pszExePath);
PathRemoveFileSpec(pszExePath);
psl->SetWorkingDirectory(pszExePath);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
// Query IShellLink for the IPersistFile interface for
// saving the shortcut in persistent storage.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile,
reinterpret_cast<void**>(&ppf));
if (SUCCEEDED(hres))
{
WCHAR pwsz[MAX_PATH];
// Ensure that the string is ANSI.
MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(pwsz, TRUE);
ppf->Release();
}
psl->Release();
}
CoUninitialize();
}
}
#else
bool GetStartOnSystemStartup() { return false; }
void SetStartOnSystemStartup(bool fAutoStart) { }
#endif

58
ui.h
View File

@@ -4,27 +4,71 @@
DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1)
#if wxUSE_GUI
static const bool fGUI=true;
#else
static const bool fGUI=false;
#endif
extern map<string, string> mapArgs;
inline int MyMessageBox(const wxString& message, const wxString& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
{
#if wxUSE_GUI
if (!fDaemon)
return wxMessageBox(message, caption, style, parent, x, y);
#endif
printf("wxMessageBox %s: %s\n", string(caption).c_str(), string(message).c_str());
fprintf(stderr, "%s: %s\n", string(caption).c_str(), string(message).c_str());
return wxOK;
}
#define wxMessageBox MyMessageBox
// Settings
extern int fMinimizeToTray;
extern int fMinimizeOnClose;
void HandleCtrlA(wxKeyEvent& event);
string FormatTxStatus(const CWalletTx& wtx);
void UIThreadCall(boost::function0<void>);
void MainFrameRepaint();
void Shutdown(void* parg);
int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent);
void CalledSetStatusBar(const string& strText, int nField);
void MainFrameRepaint();
void CreateMainWindow();
#if !wxUSE_GUI
inline int ThreadSafeMessageBox(const string& message, const string& caption, int style, wxWindow* parent, int x, int y)
{
return MyMessageBox(message, caption, style, parent, x, y);
}
inline bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent)
{
return true;
}
inline void CalledSetStatusBar(const string& strText, int nField)
{
}
inline void UIThreadCall(boost::function0<void> fn)
{
}
inline void MainFrameRepaint()
{
}
inline void CreateMainWindow()
{
}
#else // wxUSE_GUI
class CMainFrame : public CMainFrameBase
{
@@ -331,3 +375,5 @@ public:
DECLARE_EVENT_TABLE()
};
#endif // wxUSE_GUI

View File

@@ -24,7 +24,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
m_menuFile = new wxMenu();
wxMenuItem* m_menuFileExit;
m_menuFileExit = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL );
m_menuFileExit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) , wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuFileExit );
m_menubar->Append( m_menuFile, _("&File") );
@@ -39,14 +39,14 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
m_menuOptions->Append( m_menuOptionsChangeYourAddress );
wxMenuItem* m_menuOptionsOptions;
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_MENUOPTIONSOPTIONS, wxString( _("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_PREFERENCES, wxString( _("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuOptions->Append( m_menuOptionsOptions );
m_menubar->Append( m_menuOptions, _("&Settings") );
m_menuHelp = new wxMenu();
wxMenuItem* m_menuHelpAbout;
m_menuHelpAbout = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&About...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuHelpAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuHelp->Append( m_menuHelpAbout );
m_menubar->Append( m_menuHelp, _("&Help") );
@@ -133,7 +133,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
wxBoxSizer* bSizer11;
bSizer11 = new wxBoxSizer( wxVERTICAL );
m_listCtrlAll = new wxListCtrl( m_panel9, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxVSCROLL );
m_listCtrlAll = new wxListCtrl( m_panel9, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING );
bSizer11->Add( m_listCtrlAll, 1, wxEXPAND, 5 );
m_panel9->SetSizer( bSizer11 );
@@ -144,7 +144,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
wxBoxSizer* bSizer111;
bSizer111 = new wxBoxSizer( wxVERTICAL );
m_listCtrlSentReceived = new wxListCtrl( m_panel91, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxVSCROLL );
m_listCtrlSentReceived = new wxListCtrl( m_panel91, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING );
bSizer111->Add( m_listCtrlSentReceived, 1, wxEXPAND, 5 );
m_panel91->SetSizer( bSizer111 );
@@ -155,7 +155,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
wxBoxSizer* bSizer112;
bSizer112 = new wxBoxSizer( wxVERTICAL );
m_listCtrlSent = new wxListCtrl( m_panel92, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxVSCROLL );
m_listCtrlSent = new wxListCtrl( m_panel92, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING );
bSizer112->Add( m_listCtrlSent, 1, wxEXPAND, 5 );
m_panel92->SetSizer( bSizer112 );
@@ -166,7 +166,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
wxBoxSizer* bSizer113;
bSizer113 = new wxBoxSizer( wxVERTICAL );
m_listCtrlReceived = new wxListCtrl( m_panel93, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING|wxVSCROLL );
m_listCtrlReceived = new wxListCtrl( m_panel93, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SORT_DESCENDING );
bSizer113->Add( m_listCtrlReceived, 1, wxEXPAND, 5 );
m_panel93->SetSizer( bSizer113 );

View File

@@ -42,29 +42,28 @@
#define wxID_MAINFRAME 1000
#define wxID_OPTIONSGENERATEBITCOINS 1001
#define wxID_MENUOPTIONSOPTIONS 1002
#define wxID_BUTTONSEND 1003
#define wxID_BUTTONRECEIVE 1004
#define wxID_TEXTCTRLADDRESS 1005
#define wxID_BUTTONNEW 1006
#define wxID_BUTTONCOPY 1007
#define wxID_TRANSACTIONFEE 1008
#define wxID_PROXYIP 1009
#define wxID_PROXYPORT 1010
#define wxID_TEXTCTRLPAYTO 1011
#define wxID_BUTTONPASTE 1012
#define wxID_BUTTONADDRESSBOOK 1013
#define wxID_TEXTCTRLAMOUNT 1014
#define wxID_CHOICETRANSFERTYPE 1015
#define wxID_LISTCTRL 1016
#define wxID_BUTTONRENAME 1017
#define wxID_PANELSENDING 1018
#define wxID_LISTCTRLSENDING 1019
#define wxID_PANELRECEIVING 1020
#define wxID_LISTCTRLRECEIVING 1021
#define wxID_BUTTONDELETE 1022
#define wxID_BUTTONEDIT 1023
#define wxID_TEXTCTRL 1024
#define wxID_BUTTONSEND 1002
#define wxID_BUTTONRECEIVE 1003
#define wxID_TEXTCTRLADDRESS 1004
#define wxID_BUTTONNEW 1005
#define wxID_BUTTONCOPY 1006
#define wxID_TRANSACTIONFEE 1007
#define wxID_PROXYIP 1008
#define wxID_PROXYPORT 1009
#define wxID_TEXTCTRLPAYTO 1010
#define wxID_BUTTONPASTE 1011
#define wxID_BUTTONADDRESSBOOK 1012
#define wxID_TEXTCTRLAMOUNT 1013
#define wxID_CHOICETRANSFERTYPE 1014
#define wxID_LISTCTRL 1015
#define wxID_BUTTONRENAME 1016
#define wxID_PANELSENDING 1017
#define wxID_LISTCTRLSENDING 1018
#define wxID_PANELRECEIVING 1019
#define wxID_LISTCTRLRECEIVING 1020
#define wxID_BUTTONDELETE 1021
#define wxID_BUTTONEDIT 1022
#define wxID_TEXTCTRL 1023
///////////////////////////////////////////////////////////////////////////////
/// Class CMainFrameBase
@@ -78,7 +77,6 @@ class CMainFrameBase : public wxFrame
wxMenu* m_menuFile;
wxMenu* m_menuHelp;
wxToolBar* m_toolBar;
wxStatusBar* m_statusBar;
wxStaticText* m_staticText32;
wxButton* m_buttonNew;
@@ -122,6 +120,7 @@ class CMainFrameBase : public wxFrame
public:
wxMenu* m_menuOptions;
wxStatusBar* m_statusBar;
wxTextCtrl* m_textCtrlAddress;
wxListCtrl* m_listCtrlAll;
wxListCtrl* m_listCtrlSentReceived;

View File

@@ -123,7 +123,7 @@
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="id">wxID_EXIT</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">E&amp;xit</property>
<property name="name">m_menuFileExit</property>
@@ -173,7 +173,7 @@
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_MENUOPTIONSOPTIONS</property>
<property name="id">wxID_PREFERENCES</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">&amp;Options...</property>
<property name="name">m_menuOptionsOptions</property>
@@ -193,7 +193,7 @@
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="id">wxID_ABOUT</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">&amp;About...</property>
<property name="name">m_menuHelpAbout</property>
@@ -293,7 +293,7 @@
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_statusBar</property>
<property name="permission">protected</property>
<property name="permission">public</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style">wxST_SIZEGRIP</property>
@@ -924,7 +924,7 @@
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxVSCROLL</property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
@@ -1047,7 +1047,7 @@
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxVSCROLL</property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
@@ -1170,7 +1170,7 @@
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxVSCROLL</property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
@@ -1293,7 +1293,7 @@
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxVSCROLL</property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>

View File

@@ -13,6 +13,7 @@ bool fPrintToDebugger = false;
char pszSetDataDir[MAX_PATH] = "";
bool fShutdown = false;
bool fDaemon = false;
bool fCommandLine = false;
@@ -249,11 +250,6 @@ string strprintf(const char* format, ...)
if (p == NULL)
throw std::bad_alloc();
}
#ifdef _MSC_VER
// msvc optimisation
if (p == buffer)
return string(p, p+ret);
#endif
string str(p, p+ret);
if (p != buffer)
delete p;
@@ -281,15 +277,21 @@ bool error(const char* format, ...)
void ParseString(const string& str, char c, vector<string>& v)
{
unsigned int i1 = 0;
unsigned int i2;
do
if (str.empty())
return;
string::size_type i1 = 0;
string::size_type i2;
loop
{
i2 = str.find(c, i1);
if (i2 == str.npos)
{
v.push_back(str.substr(i1));
return;
}
v.push_back(str.substr(i1, i2-i1));
i1 = i2+1;
}
while (i2 != str.npos);
}
@@ -307,6 +309,12 @@ string FormatMoney(int64 n, bool fPlus)
return str;
}
bool ParseMoney(const string& str, int64& nRet)
{
return ParseMoney(str.c_str(), nRet);
}
bool ParseMoney(const char* pszIn, int64& nRet)
{
string strWhole;
@@ -444,20 +452,21 @@ const char* wxGetTranslation(const char* pszEnglish)
return (*mi).second;
// wxWidgets translation
const char* pszTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8)).utf8_str();
wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8));
// We don't cache unknown strings because caller might be passing in a
// dynamic string and we would keep allocating memory for each variation.
if (strcmp(pszEnglish, pszTranslated) == 0)
if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0)
return pszEnglish;
// Add to cache, memory doesn't need to be freed. We only cache because
// we must pass back a pointer to permanently allocated memory.
char* pszCached = new char[strlen(pszTranslated)+1];
strcpy(pszCached, pszTranslated);
char* pszCached = new char[strlen(strTranslated.utf8_str())+1];
strcpy(pszCached, strTranslated.utf8_str());
mapCache[pszEnglish] = pszCached;
return pszCached;
}
return NULL;
}
@@ -500,8 +509,9 @@ void PrintException(std::exception* pex, const char* pszThread)
char pszMessage[1000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
if (wxTheApp)
wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
if (wxTheApp && !fDaemon && fGUI)
MyMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
throw;
//DebugBreak();
}

2
util.h
View File

@@ -121,6 +121,7 @@ extern bool fPrintToDebugger;
extern char pszSetDataDir[MAX_PATH];
extern bool fShutdown;
extern bool fDaemon;
extern bool fCommandLine;
void RandAddSeed();
void RandAddSeedPerfmon();
@@ -132,6 +133,7 @@ void PrintException(std::exception* pex, const char* pszThread);
void LogException(std::exception* pex, const char* pszThread);
void ParseString(const string& str, char c, vector<string>& v);
string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const string& str, int64& nRet);
bool ParseMoney(const char* pszIn, int64& nRet);
vector<unsigned char> ParseHex(const char* psz);
vector<unsigned char> ParseHex(const std::string& str);