Merge pull request #376 from codler/translate
authorJeff Garzik <jgarzik@exmulti.com>
Fri, 8 Jul 2011 17:36:49 +0000 (10:36 -0700)
committerJeff Garzik <jgarzik@exmulti.com>
Fri, 8 Jul 2011 17:36:49 +0000 (10:36 -0700)
Minor translation changes for latest build (Swedish)

65 files changed:
contrib/Bitcoin.app/Contents/Info.plist [new file with mode: 0644]
contrib/Bitcoin.app/Contents/MacOS/.higit [new file with mode: 0644]
contrib/Bitcoin.app/Contents/Resources/BitcoinAppIcon.icns [new file with mode: 0644]
contrib/gitian-win32.yml [new file with mode: 0644]
contrib/gitian.yml
contrib/wx-patches/README [new file with mode: 0644]
contrib/wx-patches/toplevel.cpp.diff [new file with mode: 0644]
contrib/wx-patches/toplevel.h.diff [new file with mode: 0644]
doc/README
doc/README_windows.txt
doc/build-osx.txt
doc/release-process.txt
locale/cs/LC_MESSAGES/bitcoin.mo
locale/cs/LC_MESSAGES/bitcoin.po
locale/de/LC_MESSAGES/bitcoin.mo
locale/de/LC_MESSAGES/bitcoin.po
locale/eo/LC_MESSAGES/bitcoin.mo
locale/eo/LC_MESSAGES/bitcoin.po
locale/es/LC_MESSAGES/bitcoin.mo
locale/es/LC_MESSAGES/bitcoin.po
locale/it/LC_MESSAGES/bitcoin.mo
locale/it/LC_MESSAGES/bitcoin.po
locale/lt/LC_MESSAGES/bitcoin.mo
locale/lt/LC_MESSAGES/bitcoin.po
locale/nl/LC_MESSAGES/bitcoin.mo
locale/nl/LC_MESSAGES/bitcoin.po
locale/pl/LC_MESSAGES/bitcoin.po [new file with mode: 0644]
locale/ru/LC_MESSAGES/bitcoin.mo
locale/ru/LC_MESSAGES/bitcoin.po
locale/zh_cn/LC_MESSAGES/bitcoin.mo
locale/zh_cn/LC_MESSAGES/bitcoin.po
share/setup.nsi
src/db.cpp
src/db.h
src/headers.h
src/init.cpp
src/init.h
src/irc.cpp
src/keystore.cpp [new file with mode: 0644]
src/keystore.h [new file with mode: 0644]
src/main.cpp
src/main.h
src/makefile.linux-mingw [new file with mode: 0644]
src/makefile.mingw
src/makefile.osx
src/makefile.unix
src/makefile.vc
src/net.cpp
src/net.h
src/noui.h
src/obj/test/.gitignore [new file with mode: 0644]
src/rpc.cpp
src/script.cpp
src/script.h
src/serialize.h
src/test/README [new file with mode: 0644]
src/test/test_bitcoin.cpp [new file with mode: 0644]
src/test/uint160_tests.cpp [new file with mode: 0644]
src/test/uint256_tests.cpp [new file with mode: 0644]
src/ui.cpp
src/ui.h
src/util.cpp
src/util.h
src/wallet.cpp [new file with mode: 0644]
src/wallet.h [new file with mode: 0644]

diff --git a/contrib/Bitcoin.app/Contents/Info.plist b/contrib/Bitcoin.app/Contents/Info.plist
new file mode 100644 (file)
index 0000000..9a2eccc
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDisplayName</key>
+       <string>Bitcoin</string>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>bitcoin</string>
+       <key>CFBundleIdentifier</key>
+       <string>org.bitcoin.bitcoin</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>Bitcoin</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>0.3.24</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>324</string>
+       <key>LSMinimumSystemVersion</key>
+       <string>10.5</string>
+       <key>CFBundleIconFile</key>
+       <string>BitcoinAppIcon.icns</string>
+       <key>LSMultipleInstancesProhibited</key>
+       <true/>
+</dict>
+</plist>
diff --git a/contrib/Bitcoin.app/Contents/MacOS/.higit b/contrib/Bitcoin.app/Contents/MacOS/.higit
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/contrib/Bitcoin.app/Contents/Resources/BitcoinAppIcon.icns b/contrib/Bitcoin.app/Contents/Resources/BitcoinAppIcon.icns
new file mode 100644 (file)
index 0000000..033ce1a
Binary files /dev/null and b/contrib/Bitcoin.app/Contents/Resources/BitcoinAppIcon.icns differ
diff --git a/contrib/gitian-win32.yml b/contrib/gitian-win32.yml
new file mode 100644 (file)
index 0000000..07d31c7
--- /dev/null
@@ -0,0 +1,84 @@
+---
+name: "bitcoin"
+suites:
+- "lucid"
+architectures:
+- "i386"
+packages: 
+- "mingw32"
+- "git-core"
+- "unzip"
+- "nsis"
+reference_datetime: "2011-01-30 00:00:00"
+remotes:
+- "url": "https://github.com/bitcoin/bitcoin.git"
+  "dir": "bitcoin"
+files:
+- "wxWidgets-2.9.1.tar.bz2"
+- "boost_1_43_0.tar.bz2"
+- "openssl-1.0.0d.tar.gz"
+- "db-4.7.25.NC.tar.gz"
+- "upnpc-exe-win32-20110215.zip"
+- "miniupnpc-1.5.20110215.tar.gz"
+- "WSPiApi.h"
+script: |
+  #
+  tar xjf wxWidgets-2.9.1.tar.bz2
+  cd wxWidgets-2.9.1
+  ./configure --host=i586-mingw32msvc --build=i686-linux --disable-shared --enable-monolithic --without-libpng --disable-svg
+  perl -i -p -e "s/__TIME__/\"$REFERENCE_TIME\"/;s/__DATE__/\"$REFERENCE_DATE\"/" include/wx/chartype.h
+  make $MAKEOPTS
+  cd ..
+  #
+  tar xzf openssl-1.0.0d.tar.gz
+  cd openssl-1.0.0d
+  ./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
+  make
+  cd ..
+  #
+  tar xzf db-4.7.25.NC.tar.gz
+  cd db-4.7.25.NC/build_unix
+  ../dist/configure --enable-mingw --enable-cxx --host=i586-mingw32msvc CFLAGS="-I/usr/i586-mingw32msvc/include"
+  make $MAKEOPTS
+  cd ../..
+  #
+  tar xjf boost_1_43_0.tar.bz2
+  cd boost_1_43_0
+  echo "using gcc : 4.4 : i586-mingw32msvc-g++
+        :
+        <rc>i586-mingw32msvc-windres
+        <archiver>i586-mingw32msvc-ar
+  ;" > user-config.jam
+  ./bootstrap.sh --without-icu
+  ./bjam toolset=gcc target-os=windows threadapi=win32 threading=multi --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete $MAKEOPTS stage
+  cd ..
+  #
+  mkdir upnpc-exe-win32-20110215
+  cd upnpc-exe-win32-20110215
+  unzip ../upnpc-exe-win32-20110215.zip
+  mkdir miniupnpc
+  cd miniupnpc
+  tar xzf ../../miniupnpc-1.5.20110215.tar.gz
+  mv ./miniupnpc-1.5.20110215/* ./
+  cd ../..
+  #
+  cp WSPiApi.h $HOME/build
+  #
+  cd bitcoin
+  mkdir -p $OUTDIR/src
+  cp -a . $OUTDIR/src
+  rm -rf $OUTDIR/src/.git
+  cp -a $OUTDIR/src/locale $OUTDIR
+  cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt
+  cp $OUTDIR/src/COPYING $OUTDIR/license.txt
+  cd src
+  sed 's/$(DEBUGFLAGS)//' < makefile.linux-mingw > makefile.linux-mingw.2 && mv makefile.linux-mingw.2 makefile.linux-mingw
+  sed 's|//#include <WSPiApi.h>|#include <WSPiApi.h>|' < net.cpp > net.cpp.2 && mv net.cpp.2 net.cpp
+  make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoin.exe USE_UPNP=1
+  make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0
+  i586-mingw32msvc-strip bitcoin.exe
+  i586-mingw32msvc-strip bitcoind.exe
+  makensis ../share/setup.nsi
+  cp bitcoin.exe ../share/bitcoin-*-win32-setup.exe $OUTDIR/
+  mkdir $OUTDIR/daemon
+  cp bitcoind.exe $OUTDIR/daemon
index bf99750..90be893 100644 (file)
@@ -6,7 +6,7 @@ architectures:
 - "i386"
 - "amd64"
 packages: 
-- "libdb4.8++-dev"
+- "libdb4.7++-dev"
 - "libxxf86vm-dev"
 - "libgtk2.0-dev"
 - "libboost-all-dev"
@@ -19,6 +19,8 @@ remotes:
 files:
 - "wxWidgets-2.9.1.tar.bz2"
 - "miniupnpc-1.5.tar.gz"
+- "toplevel.h.diff"
+- "toplevel.cpp.diff"
 script: |
   INSTDIR="$HOME/install"
   export LIBRARY_PATH="$INSTDIR/lib"
@@ -30,6 +32,11 @@ script: |
   #
   tar xjf wxWidgets-2.9.1.tar.bz2
   cd wxWidgets-2.9.1
+  cd include/wx/gtk
+  patch < ../../../../toplevel.h.diff
+  cd ../../../src/gtk
+  patch < ../../../toplevel.cpp.diff
+  cd ../..
   ./configure --prefix=$INSTDIR --enable-monolithic --disable-shared
   perl -i -p -e "s/__TIME__/\"$REFERENCE_TIME\"/;s/__DATE__/\"$REFERENCE_DATE\"/" include/wx/chartype.h
   make $MAKEOPTS install
@@ -43,6 +50,8 @@ script: |
   cp $OUTDIR/src/doc/README $OUTDIR
   cp $OUTDIR/src/COPYING $OUTDIR
   cd src
-  PATH=$INSTDIR/bin:$PATH make -f makefile.unix CXX="g++ -I$INSTDIR/include -L$INSTDIR/lib" $MAKEOPTS bitcoin bitcoind
+  sed 's/$(DEBUGFLAGS)//' < makefile.unix > makefile.unix.2 && mv makefile.unix.2 makefile.unix
+  PATH=$INSTDIR/bin:$PATH make -f makefile.unix CXX="g++ -I$INSTDIR/include -L$INSTDIR/lib" $MAKEOPTS bitcoin USE_UPNP=1
+  PATH=$INSTDIR/bin:$PATH make -f makefile.unix CXX="g++ -I$INSTDIR/include -L$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0
   mkdir -p $OUTDIR/bin/$GBUILD_BITS
   install -s bitcoin bitcoind $OUTDIR/bin/$GBUILD_BITS
diff --git a/contrib/wx-patches/README b/contrib/wx-patches/README
new file mode 100644 (file)
index 0000000..2afb4a9
--- /dev/null
@@ -0,0 +1,4 @@
+This folder contains two patches which are applied to wxWidgets
+2.9.1 before building the wxWidgets which is used for release
+versions of bitcoin.  They make the GUI show up on newer OSs
+with new libgtks, such as Ubuntu 11.04.
diff --git a/contrib/wx-patches/toplevel.cpp.diff b/contrib/wx-patches/toplevel.cpp.diff
new file mode 100644 (file)
index 0000000..359abf2
--- /dev/null
@@ -0,0 +1,86 @@
+--- /wxWidgets/trunk/src/gtk/toplevel.cpp (revision 67326)\r
++++ /wxWidgets/trunk/src/gtk/toplevel.cpp (revision 67496)\r
+@@ -72,4 +72,8 @@\r
+ // send any activate events at all\r
+ static int g_sendActivateEvent = -1;\r
++\r
++// Whether _NET_REQUEST_FRAME_EXTENTS support is working\r
++//   0 == not tested yet, 1 == working, 2 == broken\r
++static int gs_requestFrameExtentsStatus;\r
\r
+ //-----------------------------------------------------------------------------\r
+@@ -432,4 +436,12 @@\r
+     if (event->state == GDK_PROPERTY_NEW_VALUE && event->atom == property)\r
+     {\r
++        if (win->m_netFrameExtentsTimerId)\r
++        {\r
++            // WM support for _NET_REQUEST_FRAME_EXTENTS is working\r
++            gs_requestFrameExtentsStatus = 1;\r
++            g_source_remove(win->m_netFrameExtentsTimerId);\r
++            win->m_netFrameExtentsTimerId = 0;\r
++        }\r
++\r
+         wxSize decorSize = win->m_decorSize;\r
+         int left, right, top, bottom;\r
+@@ -439,4 +451,22 @@\r
+         win->GTKUpdateDecorSize(decorSize);\r
+     }\r
++    return false;\r
++}\r
++}\r
++\r
++extern "C" {\r
++static gboolean request_frame_extents_timeout(void* data)\r
++{\r
++    // WM support for _NET_REQUEST_FRAME_EXTENTS is broken\r
++    gs_requestFrameExtentsStatus = 2;\r
++    gdk_threads_enter();\r
++    wxTopLevelWindowGTK* win = static_cast<wxTopLevelWindowGTK*>(data);\r
++    win->m_netFrameExtentsTimerId = 0;\r
++    wxSize decorSize = win->m_decorSize;\r
++    int left, right, top, bottom;\r
++    if (wxGetFrameExtents(gtk_widget_get_window(win->m_widget), &left, &right, &top, &bottom))\r
++        decorSize.Set(left + right, top + bottom);\r
++    win->GTKUpdateDecorSize(decorSize);\r
++    gdk_threads_leave();\r
+     return false;\r
+ }\r
+@@ -459,4 +489,5 @@\r
+     m_deferShowAllowed = true;\r
+     m_updateDecorSize = true;\r
++    m_netFrameExtentsTimerId = 0;\r
\r
+     m_urgency_hint = -2;\r
+@@ -811,5 +842,6 @@\r
+     if (deferShow)\r
+     {\r
+-        deferShow = m_deferShowAllowed && !GTK_WIDGET_REALIZED(m_widget);\r
++        deferShow = gs_requestFrameExtentsStatus != 2 &&\r
++            m_deferShowAllowed && !gtk_widget_get_realized(m_widget);\r
+         if (deferShow)\r
+         {\r
+@@ -829,11 +861,4 @@\r
+             // GetSize()/SetSize() because it makes window bigger between each\r
+             // restore and save.\r
+-            m_updateDecorSize = deferShow;\r
+-        }\r
+-        if (deferShow)\r
+-        {\r
+-            // Fluxbox support for _NET_REQUEST_FRAME_EXTENTS is broken\r
+-            const char* name = gdk_x11_screen_get_window_manager_name(screen);\r
+-            deferShow = strcmp(name, "Fluxbox") != 0;\r
+             m_updateDecorSize = deferShow;\r
+         }\r
+@@ -875,4 +900,12 @@\r
+             (XEvent*)&xevent);\r
\r
++        if (gs_requestFrameExtentsStatus == 0)\r
++        {\r
++            // if WM does not respond to request within 1 second,\r
++            // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working\r
++            m_netFrameExtentsTimerId =\r
++                g_timeout_add(1000, request_frame_extents_timeout, this);\r
++        }\r
++\r
+         // defer calling gtk_widget_show()\r
+         m_isShown = true;\r
diff --git a/contrib/wx-patches/toplevel.h.diff b/contrib/wx-patches/toplevel.h.diff
new file mode 100644 (file)
index 0000000..c2718d4
--- /dev/null
@@ -0,0 +1,9 @@
+--- /wxWidgets/trunk/include/wx/gtk/toplevel.h (revision 65373)\r
++++ /wxWidgets/trunk/include/wx/gtk/toplevel.h (revision 67496)\r
+@@ -114,4 +114,6 @@\r
+     // wxUSER_ATTENTION_ERROR difference, -2 for no hint, -1 for ERROR hint, rest for GtkTimeout handle.\r
+     int m_urgency_hint;\r
++    // timer for detecting WM with broken _NET_REQUEST_FRAME_EXTENTS handling\r
++    unsigned m_netFrameExtentsTimerId;\r
\r
+     // return the size of the window without WM decorations\r
index 776f6aa..a4df4c2 100644 (file)
@@ -1,4 +1,4 @@
-Bitcoin 0.3.23 BETA
+Bitcoin 0.3.24 BETA
 
 Copyright (c) 2009-2011 Bitcoin Developers
 Distributed under the MIT/X11 software license, see the accompanying
index 110ba71..a19dcc9 100644 (file)
@@ -1,4 +1,4 @@
-Bitcoin 0.3.23 BETA\r
+Bitcoin 0.3.24 BETA\r
 \r
 Copyright (c) 2009-2011 Bitcoin Developers\r
 Distributed under the MIT/X11 software license, see the accompanying\r
index 7927983..ddf0250 100644 (file)
@@ -1,14 +1,16 @@
 Copyright (c) 2010 Laszlo Hanyecz
-Distributed under the MIT/X11 software license, see the accompanying
-file license.txt or http://www.opensource.org/licenses/mit-license.php.
-This product includes software developed by the OpenSSL Project for use in
-the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
-cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
-software written by Thomas Bernard.
+Portions Copyright (c) 2011 Douglas Huff
+Distributed under the MIT/X11 software license, see the accompanying file
+license.txt or http://www.opensource.org/licenses/mit-license.php.  This
+product includes software developed by the OpenSSL Project for use in the
+OpenSSL Toolkit (http://www.openssl.org/).  This product includes cryptographic
+software written by Eric Young (eay@cryptsoft.com) and UPnP software written by
+Thomas Bernard.
 
 
 Mac OS X build instructions
-Laszlo Hanyecz (solar@heliacal.net)
+Laszlo Hanyecz <solar@heliacal.net>
+Douglas Huff <dhuff@jrbobdobbs.org>
 
 
 Tested on 10.5 and 10.6 intel.  PPC is not supported because it's big-endian.
@@ -16,18 +18,19 @@ 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
+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/bitcoin       # Upstream source tree
+~/bitcoin/src           # source code (symlink to ~/bitcoin/bitcoin/src)
 ~/bitcoin/deps          # dependencies.. like libraries and headers needed to compile
 ~/bitcoin/Bitcoin.app   # the application bundle where you can run the app
 
@@ -38,12 +41,15 @@ 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:
+2.  Check out the bitcoin code from github:
 
 cd ~/bitcoin
-svn checkout https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk
+git clone https://github.com/bitcoin/bitcoin.git
+ln -s bitcoin/src src
 
-This will make ~/bitcoin/trunk for you with all the files from subversion. 
+This will make ~/bitcoin/bitcoin for you with all the files from git. This puts
+the actual sources in ~/bitcoin/bitcoin/src and create a symlink src in
+~/bitcoin to this location.
 
 3.  Get and build the dependencies
 
@@ -80,6 +86,8 @@ This is what my output looked like at the end:
 OpenSSL
 -------
 
+(System or MacPorts openssl will work fine. Optional.)
+
 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
@@ -113,13 +121,15 @@ file lib/libcrypto.a
 output should look like this:
 
 lib/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
+lib/libcrypto.a (for architecture i386):  current ar archive random library
+lib/libcrypto.a (for architecture x86_64):  current ar archive random library
 
 
 miniupnpc
 ---------
 
+(MacPorts miniupnpc package works fine. You will need to modify makefile.)
+
 The process for miniupnpc (optional) is similar to that of OpenSSL.
 
 Download from http://miniupnp.tuxfamily.org/files/.
@@ -153,13 +163,15 @@ file lib/libminiupnpc.a
 output should look like this:
 
 lib/libminiupnpc.a: Mach-O universal binary with 2 architectures
-lib/libminiupnpc.a (for architecture i386):    current ar archive random library
-lib/libminiupnpc.a (for architecture x86_64):  current ar archive random library
+lib/libminiupnpc.a (for architecture i386): current ar archive random library
+lib/libminiupnpc.a (for architecture x86_64): current ar archive random library
 
 
 Berkeley DB
 -----------
 
+(System or MacPorts version work fine.)
+
 Download from http://freshmeat.net/projects/berkeleydb/
 
 cd ~/bitcoin/deps
@@ -171,6 +183,8 @@ cd db-4.8.26/build_unix
 wxWidgets
 ---------
 
+(The wxWidgets-devel MacPorts package will work but will throw annoying assertion dialogs.)
+
 This is the big one..
 
 Check it out from svn
@@ -236,26 +250,29 @@ make install
 
 Now you should be able to build bitcoin
 
-cd ~/bitcoin/trunk
+cd ~/bitcoin/src
 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
+
+A bundle is provided in contrib/Bitcoin.app.
+
+Copy the bitcoin binary in to it like this:
+  cp -pR ~/bitcoin/bitcoin/contrib/Bitcoin.app ~/bitcoin/
+  cp ~/bitcoin/src/bitcoin ~/bitcoin/Bitcoin.app/Contents/MacOS/
+
+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
+
+You can also run it with arguments in the background with output going to the
+normal places for apps (Console) like this:
+
+open ~/bitcoin/Bitcoin.app --args -connect=192.75.207.66
+
+It is advisable to relocate Bitcoin.app to /Applications or $HOME/Applications.
+
index f888239..4940afe 100644 (file)
@@ -1,3 +1,9 @@
+* update (commit) version in sources
+
+* update (commit) version in OSX app bundle
+
+  * CFBundleShortVersionString should have value like 0.3.23
+  * CFBundleVersion should have value like 323
 
 * tag version in git
 
 
 * perform gitian builds
 
-  { insert useful info here }
+  * From the bitcoin source dir
+  $ cd ../gitian-builder
+  $ ./bin/gbuild --commit bitcoin=v0.3.23 ../bitcoin/contrib/gitian.yml
+  $ ./bin/gbuild --commit bitcoin=v0.3.23 ../bitcoin/contrib/gitian-win32.yml
  
+  Build output expected:
+  1. linux 32-bit and 64-bit binaries + source
+  2. windows 32-bit binary + source
+  3. windows installer
+
 * upload source and builds to SF
 
+* create SHA1SUMS for builds, and PGP-sign it
+
 * update bitcoin.org version
 
 * update forum version
index 4388fcc..80354cf 100644 (file)
Binary files a/locale/cs/LC_MESSAGES/bitcoin.mo and b/locale/cs/LC_MESSAGES/bitcoin.mo differ
index 13529b3..51fe182 100644 (file)
@@ -524,8 +524,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Varování: Prosím zkontroluj, že datum a čas jsou na tvém počítači správně nastaveny. Pokud jsou nastaveny špatně, Bitcoin nebude fungovat správně."
 
 #: ../../../src/util.cpp:899
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -776,10 +776,6 @@ msgstr "Tvoje adresy (pro příjem)"
 msgid "&Delete"
 msgstr "&Smazat"
 
-#: ../../../src/init.cpp:140
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:142
 msgid "Bitcoin version"
 msgstr "Bitcoin verze"
index ee2cad4..bcea1d3 100644 (file)
Binary files a/locale/de/LC_MESSAGES/bitcoin.mo and b/locale/de/LC_MESSAGES/bitcoin.mo differ
index e40c6c4..a0519f0 100644 (file)
@@ -524,8 +524,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Warnung: Bitte überprüfen Sie die Richtigkeit des Datums und der Uhrzeit Ihres Computers. Falls Ihre Uhr falsch läuft, wird Bitcoin nicht richtig funktionieren."
 
 #: ../../../src/util.cpp:898
-msgid "-beta"
-msgstr "-Beta"
+msgid "beta"
+msgstr "Beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -707,7 +707,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Geben Sie eine Bitcoin-Adresse ein (z.B. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Geben Sie eine Bitcoin-Adresse ein (z.B. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -777,10 +777,6 @@ msgstr "Empfange"
 msgid "&Delete"
 msgstr "&Löschen"
 
-#: ../../../src/init.cpp:145
-msgid " beta"
-msgstr " Beta"
-
 #: ../../../src/init.cpp:147
 msgid "Bitcoin version"
 msgstr "Bitcoin "
@@ -834,6 +830,10 @@ msgid "Connect through socks4 proxy\n"
 msgstr "Socks4-Proxy verwenden\n"
 
 #: ../../../src/init.cpp:161
+msgid "Specify connection timeout (in milliseconds)\n"
+msgstr "Verbindungs-Timeout in Milisekunden\n"
+
+#: ../../../src/init.cpp:161
 msgid "Allow DNS lookups for addnode and connect\n"
 msgstr "DNS-Auflösung für addnode und connect erlauben\n"
 
@@ -973,53 +973,3 @@ msgstr "Über Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "Ihre Bitcoin-Adressen"
-
-#~ msgid "Usage: bitcoin [options]"
-#~ msgstr "Verwendung: bitcoin [optionen]"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr ""
-#~ "Fehler: Die Überweisung ist sehr groß. Es wird eine Gebühr von %s "
-#~ "erhoben.  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "Version %s%s BETA"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "Wird als \"Von: Unbekannt\" erscheinen"
-
-#~ msgid "n/a"
-#~ msgstr "Unbekannt"
-
-#~ msgid "Unknown"
-#~ msgstr "Unbekannt"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr ""
-#~ "Beim Überweisen an eine Bitcoin-Adresse kann keine Nachricht angegeben "
-#~ "werden."
-
-#~ msgid ""
-#~ "This is an oversized transaction that requires a transaction fee of %s"
-#~ msgstr "Die Überweisung ist sehr groß. Es wird eine Gebühr von %s erhoben."
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr ""
-#~ "Optionale Überweisungsgebühr, die Sie an den Teilnehmer entrichten, der "
-#~ "Ihre Überweisungen bearbeitet."
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "Erzeugung von Münzen auf"
-
-#~ msgid "processors"
-#~ msgstr "Prozessoren &beschränken"
-
-#~ msgid "&From:"
-#~ msgstr "&Von:"
-
-#~ msgid "&Message:"
-#~ msgstr "&Nachricht:"
index 592aecc..5f898f2 100644 (file)
Binary files a/locale/eo/LC_MESSAGES/bitcoin.mo and b/locale/eo/LC_MESSAGES/bitcoin.mo differ
index 71d639e..e144cd8 100644 (file)
@@ -557,8 +557,8 @@ msgstr ""
 "ĝusta. Se viaj horloĝo malĝustas, Bitmonero ne funkcios korekte."\r
 \r
 #: ../../../src/util.cpp:898\r
-msgid "-beta"\r
-msgstr "-beta"\r
+msgid "beta"\r
+msgstr "beta"\r
 \r
 #: ../../../src/uibase.cpp:28\r
 msgid "&File"\r
@@ -743,7 +743,7 @@ msgstr ""
 \r
 #: ../../../src/uibase.cpp:581\r
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"\r
-msgstr "Entajpu bitmoneran adreson (ekz. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"\r
+msgstr "Entajpu bitmoneran adreson (ekz. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"\r
 \r
 #: ../../../src/uibase.cpp:595\r
 msgid "Pay &To:"\r
@@ -823,10 +823,6 @@ msgstr "Ricevanta"
 msgid "&Delete"\r
 msgstr "&Viŝu"\r
 \r
-#: ../../../src/init.cpp:145\r
-msgid " beta"\r
-msgstr " beta"\r
-\r
 #: ../../../src/init.cpp:147\r
 msgid "Bitcoin version"\r
 msgstr "Versio de Bitmonero"\r
@@ -1031,51 +1027,3 @@ msgstr "Pri Bitmonero"
 #: ../../../src/uibase.h:337\r
 msgid "Your Bitcoin Addresses"\r
 msgstr "Viaj Bitmoneraj adresoj"\r
-\r
-#~ msgid "Usage: bitcoin [options]"\r
-#~ msgstr "Uzado: bitcoin [opcioj]"\r
-\r
-#~ msgid ""\r
-#~ "Error: This is an oversized transaction that requires a transaction fee "\r
-#~ "of %s  "\r
-#~ msgstr ""\r
-#~ "Eraro: Tiu ĉi estas grandega transakcio, kiu necesas transakcian koston "\r
-#~ "de %s.  "\r
-\r
-#~ msgid "version %s%s BETA"\r
-#~ msgstr "versio %s%s BETA"\r
-\r
-#~ msgid "Will appear as \"From: Unknown\""\r
-#~ msgstr "Vidigonta kiel \"De: Nekonata\""\r
-\r
-#~ msgid "n/a"\r
-#~ msgstr "n/d"\r
-\r
-#~ msgid "Unknown"\r
-#~ msgstr "Nekonata"\r
-\r
-#~ msgid "Can't include a message when sending to a Bitcoin address"\r
-#~ msgstr "Sendante al bitmonaran adreson ne povas inkludi mesaĝon"\r
-\r
-#~ msgid ""\r
-#~ "This is an oversized transaction that requires a transaction fee of %s"\r
-#~ msgstr "Tiu ĉi estas grandega transakcio, kiu necesas transakcian koston de %s"\r
-\r
-#~ msgid ""\r
-#~ "Optional transaction fee you give to the nodes that process your "\r
-#~ "transactions."\r
-#~ msgstr ""\r
-#~ "Opcian transakcian koston vi donas al la nodoj kiuj plenumas viajn "\r
-#~ "transakciojn."\r
-\r
-#~ msgid "&Limit coin generation to"\r
-#~ msgstr "&Limitu bitmoneran kreadon al"\r
-\r
-#~ msgid "processors"\r
-#~ msgstr "procesoroj"\r
-\r
-#~ msgid "&From:"\r
-#~ msgstr "&De:"\r
-\r
-#~ msgid "&Message:"\r
-#~ msgstr "&Mesaĝo:"
\ No newline at end of file
index f9d84ce..e22b894 100644 (file)
Binary files a/locale/es/LC_MESSAGES/bitcoin.mo and b/locale/es/LC_MESSAGES/bitcoin.mo differ
index 98203cc..c67886e 100644 (file)
@@ -521,8 +521,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Precaución: Por favor revisa que la fecha y hora de tu computador son correctas. Si tu reloj está mal, Bitcoin no funcionará correctamente."
 
 #: ../../../src/util.cpp:899
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -703,7 +703,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Ponga una dirección Bitcoin (ejemplo: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Ponga una dirección Bitcoin (ejemplo: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -773,10 +773,6 @@ msgstr "Recibiendo"
 msgid "&Delete"
 msgstr "&Borrar"
 
-#: ../../../src/init.cpp:140
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:142
 msgid "Bitcoin version"
 msgstr "versión Bitcoin"
@@ -969,51 +965,3 @@ msgstr "Acerca de Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "Sus direcciones Bitcoin"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr ""
-#~ "Error: Esta es una gran transaccion que requiere una comision de %s  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "version %s%s BETA"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "Aparecera como \"De: Desconocido\""
-
-#~ msgid "n/a"
-#~ msgstr "Desconocido"
-
-#~ msgid "Unknown"
-#~ msgstr "Desconocido"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr ""
-#~ "No se ha podido incluir un mensaje mientras se enviaba la direccion "
-#~ "Bitcoin"
-
-#~ msgid ""
-#~ "This is an oversized transaction that requires a transaction fee of %s"
-#~ msgstr "Esta es una gran transaccion que requiere una comision de %s"
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr ""
-#~ "Comision opcional que se da a los nodos que procesan sus transacciones"
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "&Limitar la generacion de monedas a"
-
-#~ msgid "processors"
-#~ msgstr "procesadores"
-
-#~ msgid "&From:"
-#~ msgstr "&De:"
-
-#~ msgid "&Message:"
-#~ msgstr "&Mensaje:"
-
-#~ msgid "Usage: bitcoin [options]"
-#~ msgstr "Uso: bitcoin [opciones]"
index 24a7495..12386bc 100644 (file)
Binary files a/locale/it/LC_MESSAGES/bitcoin.mo and b/locale/it/LC_MESSAGES/bitcoin.mo differ
index 75f32b5..c041b1e 100644 (file)
@@ -521,8 +521,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Attenzione: Controlla che data/ora del tuo computer siano corrette. Se il tuo orologio è sbagliato bitcoin non funzionerà correttamente"
 
 #: ../../../src/util.cpp:898
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -703,7 +703,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Inserisci un indirizzo Bitcoin (es. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Inserisci un indirizzo Bitcoin (es. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -773,10 +773,6 @@ msgstr "Ricevendo"
 msgid "&Delete"
 msgstr "&Cancella"
 
-#: ../../../src/init.cpp:145
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:147
 msgid "Bitcoin version"
 msgstr "Versione Bitcoin "
@@ -969,55 +965,3 @@ msgstr "Info Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "Il tuo indirizzo Bitcoin"
-
-#~ msgid "Usage: bitcoin [options]"
-#~ msgstr "Uso: bitcoin [options]"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr ""
-#~ "Errore: Questa è un operazione fuorimisura che richiede un sovrapprezzo"
-#~ "di %s  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "versione %s%s BETA"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "Apparirà come \"Da: Sconosciuto\""
-
-#~ msgid "n/a"
-#~ msgstr "Non disponibile"
-
-#~ msgid "Unknown"
-#~ msgstr "Sconosciuto"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr ""
-#~ "Non si può includere un messaggio quando si invia attraverso l'indirizzo "
-#~ "Bitcoin"
-
-#~ msgid ""
-#~ "This is an oversized transaction that requires a transaction fee of %s"
-#~ msgstr ""
-#~ "Questo è un trasferimento fuorimisura che richiede un costo aggiuntivo di %s "
-
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr ""
-#~ "Costo aggiuntivo opzionale che tu dai ai nodi che realizzano i tuoi "
-#~ "trasferimenti"
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "&Limita la generazione di Bitcoin a"
-
-#~ msgid "processors"
-#~ msgstr "processori"
-
-#~ msgid "&From:"
-#~ msgstr "&Proveniente da:"
-
-#~ msgid "&Message:"
-#~ msgstr "&Messaggio:"
index 22a42c5..bba16a8 100644 (file)
Binary files a/locale/lt/LC_MESSAGES/bitcoin.mo and b/locale/lt/LC_MESSAGES/bitcoin.mo differ
index e73122a..b0decb2 100644 (file)
@@ -522,8 +522,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Perspėjimas: Prašome patikrinti kompiuterio laiką ir datą. Jei laikas neteisingai nustatytas, Bitcoin neveiks."
 
 #: ../../../src/util.cpp:899
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -706,7 +706,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Įveskite Bitcoin adresą (pvz.: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Įveskite Bitcoin adresą (pvz.: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -776,10 +776,6 @@ msgstr "Priėmimo"
 msgid "&Delete"
 msgstr "&Ištrinti"
 
-#: ../../../src/init.cpp:140
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:142
 msgid "Bitcoin version"
 msgstr "Bitcoin version"
@@ -973,55 +969,3 @@ msgstr "Apie Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "Jūsų Bitcoin Adresas"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr ""
-#~ "Klaida: Šis pervedimas yra labai didelis ir reikalauja %s pervedimo mokesčio "
-#~ "%s  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "versija %s%s beta"
-
-#~ msgid "n/a"
-#~ msgstr "netaikoma"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr "Negalite pridėti žinutės kai siunčiate i Bitcoin adresą"
-
-#~ msgid ""
-#~ "This is an oversized transaction that requires a transaction fee of %s"
-#~ msgstr "Šis pervedimas yra per didelis ir reikalauja pervedimo mokesčio %s"
-
-#~ msgid "&Generate Coins"
-#~ msgstr "&Generuoti monetas"
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr "Pasirinktinas pervedimo mokestis, kurį duodate tinklo nodams."
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "&Apriboti monetų generavima iki"
-
-#~ msgid "processors"
-#~ msgstr "procesorių"
-
-#~ msgid "&From:"
-#~ msgstr "&Nuo:"
-
-#~ msgid "&Message:"
-#~ msgstr "Ž&inutė:"
-
-#~ msgid ""
-#~ "It's good policy to use a new address for each payment you receive.\n"
-#~ "\n"
-#~ "Label"
-#~ msgstr ""
-#~ "Rekomenduojama naudoti naują adresą kiekvienam pervedimui, kurį jūs gaunate.\n"
-#~ "\n"
-#~ "Pavadinimas"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "Bus rodoma kaip \"Nuo: Nežinomo\""
index 3a80d8f..c5ae848 100644 (file)
Binary files a/locale/nl/LC_MESSAGES/bitcoin.mo and b/locale/nl/LC_MESSAGES/bitcoin.mo differ
index a98ba1f..97216ad 100644 (file)
@@ -511,19 +511,19 @@ msgstr ""
 msgid ""
 "You must set rpcpassword=<password> in the configuration file:\n"
 "%s\n"
-"If the file does not exist, create it with owner-readable-only file permissions.\n"
+"If the file does not exist, create it with owner-readable-only file permissions."
 msgstr ""
 "rpcpassword=<password> moet ingesteld in het configuratie bestand:\n"
 "%s\n"
-"Als het bestand nog niet bestaat, maak het dan aan met enkel-leesbaar-door-eigenaar rechten.\n"
+"Als het bestand nog niet bestaat, maak het dan aan met enkel-leesbaar-door-eigenaar rechten."
 
 #: ../../../src/util.cpp:865
 msgid "Warning: Please check that your computer's date and time are correct.  If your clock is wrong Bitcoin will not work properly."
 msgstr "Waarschuwing: Controleer of uw computers datum en tijd correct ingesteld zijn. Als uw klok fout staat zal Bitcoin niet correct werken."
 
 #: ../../../src/util.cpp:898
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -705,7 +705,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Voer een bitcoin-adres (bijvoorbeeld: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Voer een bitcoin-adres (bijvoorbeeld: 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -775,10 +775,6 @@ msgstr "Ontvangen..."
 msgid "&Delete"
 msgstr "&Verwijderen"
 
-#: ../../../src/init.cpp:145
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:147
 msgid "Bitcoin version"
 msgstr "Bitcoin "
@@ -827,6 +823,10 @@ msgstr "Geminimaliseerd starten\n"
 msgid "Specify data directory\n"
 msgstr "Stel datamap in\n"
 
+#: ../../../src/init.cpp:161
+msgid "Specify connection timeout (in milliseconds)\n"
+msgstr "Gelieve de time-out tijd te specifieren (in milliseconden)\n"
+
 #: ../../../src/init.cpp:160
 msgid "Connect through socks4 proxy\n"
 msgstr "Verbind via socks4 proxy\n"
@@ -971,49 +971,3 @@ msgstr "Over Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "Uw bitcoin-adressen"
-
-#~ msgid "Usage: bitcoin [options]"
-#~ msgstr "Commandoregel: bitcoin [opties]"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr "Fout: Dit is een te grote transactie, die een fooi vereist van %s  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "versie %s%s BETA"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "Wordt weergegeven als \"Van: Onbekend\""
-
-#~ msgid "n/a"
-#~ msgstr "Onbekend"
-
-#~ msgid "Unknown"
-#~ msgstr "Onbekend"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr "Kan geen mededeling bijvoegen bij gebruik van bitcoin-adressen"
-
-#~ msgid ""
-#~ "This is an oversized transaction that requires a transaction fee of %s"
-#~ msgstr "Fout: Dit is een te grote transactie, die een fooi vereist van %s"
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr ""
-#~ "Optionele transactiefooi die u geeft aan de nodes die uw transacties "
-#~ "verwerken."
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "&Limiteer coin-generatie tot"
-
-#~ msgid "processors"
-#~ msgstr "processors"
-
-#~ msgid "&From:"
-#~ msgstr "&Van:"
-
-#~ msgid "&Message:"
-#~ msgstr "&Mededeling:"
diff --git a/locale/pl/LC_MESSAGES/bitcoin.po b/locale/pl/LC_MESSAGES/bitcoin.po
new file mode 100644 (file)
index 0000000..ef6be0d
--- /dev/null
@@ -0,0 +1,976 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Bitcoin\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-06-28 20:11+0100\n"
+"PO-Revision-Date: \n"
+"Last-Translator: Dawid Spiechowicz <spiechu@gmail.com>\n"
+"Language-Team: Spiechu <spiechu@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"X-Poedit-Language: Polish\n"
+"X-Poedit-Country: POLAND\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
+"X-Poedit-Basepath: .\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+"X-Poedit-SearchPath-0: ../../..\n"
+
+#: ../../../src/net.cpp:1590
+#, c-format
+msgid "Unable to bind to port %d on this computer.  Bitcoin is probably already running."
+msgstr "Nie można powiązać z portem %d tego komputera. Prawdopodobnie program Bitcoin jest już uruchomiony."
+
+#: ../../../src/init.cpp:162
+msgid "Bitcoin version"
+msgstr "Wersja Bitcoin"
+
+#: ../../../src/init.cpp:163
+msgid "Usage:"
+msgstr "Użycie:"
+
+#: ../../../src/init.cpp:165
+msgid "Send command to -server or bitcoind\n"
+msgstr "Wyślij polecenie do -server lub bitcoind\n"
+
+#: ../../../src/init.cpp:166
+msgid "List commands\n"
+msgstr "Wyświetl komendy\n"
+
+#: ../../../src/init.cpp:167
+msgid "Get help for a command\n"
+msgstr "Wyświetl pomoc dla komendy\n"
+
+#: ../../../src/init.cpp:168
+msgid "Options:\n"
+msgstr "Opcje:\n"
+
+#: ../../../src/init.cpp:169
+msgid "Specify configuration file (default: bitcoin.conf)\n"
+msgstr "Określ plik konfiguracyjny (domyślnie: bitcoin.conf)\n"
+
+#: ../../../src/init.cpp:170
+msgid "Specify pid file (default: bitcoind.pid)\n"
+msgstr "Wybierz plik pid (domyślnie: bitcoind.pid)\n"
+
+#: ../../../src/init.cpp:171
+msgid "Generate coins\n"
+msgstr "Generuj monety\n"
+
+#: ../../../src/init.cpp:172
+msgid "Don't generate coins\n"
+msgstr "Nie generuj monet\n"
+
+#: ../../../src/init.cpp:173
+msgid "Start minimized\n"
+msgstr "Uruchom zminimalizowany\n"
+
+#: ../../../src/init.cpp:174
+msgid "Specify data directory\n"
+msgstr "Wybierz katalog z danymi\n"
+
+#: ../../../src/init.cpp:175
+msgid "Specify connection timeout (in milliseconds)\n"
+msgstr "Ustaw czas upływu połączenia (w milisekundach)\n"
+
+#: ../../../src/init.cpp:176
+msgid "Connect through socks4 proxy\n"
+msgstr "Połącz przez socks4 proxy\n"
+
+#: ../../../src/init.cpp:177
+msgid "Allow DNS lookups for addnode and connect\n"
+msgstr "Umożliwiaj wyszukiwanie DNS dla dodania węzła i połączenia\n"
+
+#: ../../../src/init.cpp:178
+msgid "Add a node to connect to\n"
+msgstr "Dodaj węzeł do którego połączyć\n"
+
+#: ../../../src/init.cpp:179
+msgid "Connect only to the specified node\n"
+msgstr "Łącz tylko z wybranym węzłem\n"
+
+#: ../../../src/init.cpp:180
+msgid "Don't accept connections from outside\n"
+msgstr "Nie akceptuj połączeń z zewnątrz\n"
+
+#: ../../../src/init.cpp:183
+msgid "Don't attempt to use UPnP to map the listening port\n"
+msgstr "Nie próbuj użyć UPnP dla mapowania portu nasłuchu\n"
+
+#: ../../../src/init.cpp:185
+msgid "Attempt to use UPnP to map the listening port\n"
+msgstr "Próbuj użyć UPnP dla mapowania portu nasłuchu\n"
+
+#: ../../../src/init.cpp:188
+msgid "Fee per KB to add to transactions you send\n"
+msgstr "Prowizja na KB dodawana do transakcji, które wysyłasz\n"
+
+#: ../../../src/init.cpp:190
+msgid "Accept command line and JSON-RPC commands\n"
+msgstr "Akceptuj polecenia linii poleceń i JSON-RPC\n"
+
+#: ../../../src/init.cpp:193
+msgid "Run in the background as a daemon and accept commands\n"
+msgstr "Uruchom w tle (daemon) i akceptuj komendy\n"
+
+#: ../../../src/init.cpp:195
+msgid "Use the test network\n"
+msgstr "Użyj sieci testowej\n"
+
+#: ../../../src/init.cpp:196
+msgid "Username for JSON-RPC connections\n"
+msgstr "Nazwa użytkownika dla połączeń JSON-RPC\n"
+
+#: ../../../src/init.cpp:197
+msgid "Password for JSON-RPC connections\n"
+msgstr "Hasło dla połączeń JSON-RPC\n"
+
+#: ../../../src/init.cpp:198
+msgid "Listen for JSON-RPC connections on <port> (default: 8332)\n"
+msgstr "Nasłuch dla połączeń JSON-RPC na porcie <port> (domyślnie: 8332)\n"
+
+#: ../../../src/init.cpp:199
+msgid "Allow JSON-RPC connections from specified IP address\n"
+msgstr "Zezwól na połączenia JSON-RPC z adresu IP\n"
+
+#: ../../../src/init.cpp:200
+msgid "Send commands to node running on <ip> (default: 127.0.0.1)\n"
+msgstr "Wysyłaj polecenia do węzła działającego na <ip> (domyślnie: 127.0.0.1)\n"
+
+#: ../../../src/init.cpp:201
+msgid "Set key pool size to <n> (default: 100)\n"
+msgstr "Ustaw pulę kluczy na <n> (domyślnie: 100)\n"
+
+#: ../../../src/init.cpp:202
+msgid "Rescan the block chain for missing wallet transactions\n"
+msgstr "Przeszukaj łańcuch bloków w poszukiwaniu zaginionych transakcji\n"
+
+#: ../../../src/init.cpp:206
+msgid ""
+"\n"
+"SSL options: (see the Bitcoin Wiki for SSL setup instructions)\n"
+msgstr ""
+"\n"
+"Opcje SSL: (zobacz instrukcje na Bitcoin Wiki dla ustawień SSL)\n"
+
+#: ../../../src/init.cpp:207
+msgid "Use OpenSSL (https) for JSON-RPC connections\n"
+msgstr "Użyj OpenSSL (https) dla połączeń JSON-RPC\n"
+
+#: ../../../src/init.cpp:208
+msgid "Server certificate file (default: server.cert)\n"
+msgstr "Plik certyfikacji serwera (domyślnie: server.cert)\n"
+
+#: ../../../src/init.cpp:209
+msgid "Server private key (default: server.pem)\n"
+msgstr "Klucz prywatny serwera (domyślnie: server.pem)\n"
+
+#: ../../../src/init.cpp:210
+msgid "Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n"
+msgstr "Akceptowalne szyfry (domyślnie: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n"
+
+#: ../../../src/init.cpp:214
+msgid "This help message\n"
+msgstr "Ta wiadomość pomocy\n"
+
+#: ../../../src/init.cpp:351
+#, c-format
+msgid "Cannot obtain a lock on data directory %s.  Bitcoin is probably already running."
+msgstr "Nie można korzystać z katalogu %s z danymi. Bitcoin prawdopodobnie już jest uruchomiony."
+
+#: ../../../src/init.cpp:377
+msgid "Error loading addr.dat      \n"
+msgstr "Błąd ładowania addr.dat      \n"
+
+#: ../../../src/init.cpp:383
+msgid "Error loading blkindex.dat      \n"
+msgstr "Błąd ładowania blkindex.dat      \n"
+
+#: ../../../src/init.cpp:391
+msgid "Error loading wallet.dat      \n"
+msgstr "Błąd ładowania wallet.dat      \n"
+
+#: ../../../src/init.cpp:481
+msgid "Invalid -proxy address"
+msgstr "Niewłaściwy adres -proxy"
+
+#: ../../../src/init.cpp:504
+msgid "Invalid amount for -paytxfee=<amount>"
+msgstr "Nieprawidłowa kwota w -paytxfee=<amount>"
+
+#: ../../../src/init.cpp:508
+msgid "Warning: -paytxfee is set very high.  This is the transaction fee you will pay if you send a transaction."
+msgstr "Ostrzeżenie: ustawienie -paytxfee jest bardzo wysokie. To jest prowizja transakcji, którą zapłacisz jeżeli wyślesz transakcję."
+
+#: ../../../src/rpc.cpp:1822
+#: ../../../src/rpc.cpp:1824
+#, c-format
+msgid "To use the %s option"
+msgstr "Użycie opcji %s"
+
+#: ../../../src/rpc.cpp:1826
+#, c-format
+msgid ""
+"Warning: %s, you must set rpcpassword=<password>\n"
+"in the configuration file: %s\n"
+"If the file does not exist, create it with owner-readable-only file permissions.\n"
+msgstr ""
+"Ostrzeżenie: %s, musisz ustawić rpcpassword=<password>\n"
+"w pliku konfiguracyjnym: %s\n"
+"Jeżeli plik nie istnieje, utwórz go z uprawnieniami tylko do odczytu dla właściciela.\n"
+
+#: ../../../src/rpc.cpp:1994
+#, c-format
+msgid ""
+"You must set rpcpassword=<password> in the configuration file:\n"
+"%s\n"
+"If the file does not exist, create it with owner-readable-only file permissions."
+msgstr ""
+"Musisz ustawić rpcpassword=<password> w pliku konfiguracyjnym:\n"
+"%s\n"
+"Jeżeli plik nie istnieje, utwórz go z uprawnieniami tylko do odczytu dla właściciela."
+
+#: ../../../src/util.cpp:874
+msgid "Warning: Please check that your computer's date and time are correct.  If your clock is wrong Bitcoin will not work properly."
+msgstr "Ostrzeżenie: Sprawdź czy ustawienia daty i czasu komputera są prawidłowe. Jeżeli zegar jest źle ustawiony, Bitcoin nie będzie poprawnie działał."
+
+#: ../../../src/util.cpp:908
+msgid "beta"
+msgstr "beta"
+
+#: ../../../src/ui.cpp:216
+#, c-format
+msgid "This transaction is over the size limit.  You can still send it for a fee of %s, which goes to the nodes that process your transaction and helps to support the network.  Do you want to pay the fee?"
+msgstr "Ta transakcja jest poza limitem wielkości. W dalszym ciągu możesz wysłać ją z prowizją %s, która dotrze do węzłów przetwarzających twoją transakcję i pomoże utrzymać sieć. Chcesz zapłacić prowizję?"
+
+#: ../../../src/ui.cpp:316
+msgid "Status"
+msgstr "Status"
+
+#: ../../../src/ui.cpp:317
+msgid "Date"
+msgstr "Data"
+
+#: ../../../src/ui.cpp:318
+msgid "Description"
+msgstr "Opis"
+
+#: ../../../src/ui.cpp:319
+msgid "Debit"
+msgstr "Obciążenie"
+
+#: ../../../src/ui.cpp:320
+msgid "Credit"
+msgstr "Suma"
+
+#: ../../../src/ui.cpp:526
+#, c-format
+msgid "Open for %d blocks"
+msgstr "Otwórz na %d bloków"
+
+#: ../../../src/ui.cpp:528
+#, c-format
+msgid "Open until %s"
+msgstr "Otwarte dopóki %s"
+
+#: ../../../src/ui.cpp:534
+#, c-format
+msgid "%d/offline?"
+msgstr "%d/offline?"
+
+#: ../../../src/ui.cpp:536
+#, c-format
+msgid "%d/unconfirmed"
+msgstr "%d/niepotwierdzono"
+
+#: ../../../src/ui.cpp:538
+#, c-format
+msgid "%d confirmations"
+msgstr "%d potwierdzeń"
+
+#: ../../../src/ui.cpp:623
+msgid "Generated"
+msgstr "Wygenerowano"
+
+#: ../../../src/ui.cpp:631
+#, c-format
+msgid "Generated (%s matures in %d more blocks)"
+msgstr "Wygenerowano (%s dojrzałych w %d więcej bloków)"
+
+#: ../../../src/ui.cpp:635
+msgid "Generated - Warning: This block was not received by any other nodes and will probably not be accepted!"
+msgstr "Wygenerowano - Ostrzeżenie: Ten blok nie został otrzymany przez żaden inny węzeł i prawdopodobnie nie zostanie zaakceptowany!"
+
+#: ../../../src/ui.cpp:639
+msgid "Generated (not accepted)"
+msgstr "Wygenerowano (nie zaakceptowano)"
+
+#: ../../../src/ui.cpp:649
+msgid "From: "
+msgstr "Od:"
+
+#: ../../../src/ui.cpp:673
+msgid "Received with: "
+msgstr "Otrzymano z:"
+
+#: ../../../src/ui.cpp:719
+msgid "Payment to yourself"
+msgstr "Płatność dla siebie samego"
+
+#: ../../../src/ui.cpp:753
+msgid "To: "
+msgstr "Do:"
+
+#: ../../../src/ui.cpp:1068
+msgid "    Generating"
+msgstr "    Generowanie"
+
+#: ../../../src/ui.cpp:1070
+msgid "(not connected)"
+msgstr "(nie połączony)"
+
+#: ../../../src/ui.cpp:1073
+#, c-format
+msgid "     %d connections     %d blocks     %d transactions"
+msgstr "     %d połączeń     %d bloków     %d transakcji"
+
+#: ../../../src/ui.cpp:1178
+#: ../../../src/ui.cpp:2571
+msgid "New Receiving Address"
+msgstr "Nowy Adres Odbiorczy"
+
+#: ../../../src/ui.cpp:1179
+#: ../../../src/ui.cpp:2572
+msgid ""
+"You should use a new address for each payment you receive.\n"
+"\n"
+"Label"
+msgstr ""
+"Powinieneś użyć nowego adresu dla każdej płatności, którą otrzymasz.\n"
+"\n"
+"Etykieta"
+
+#: ../../../src/ui.cpp:1251
+msgid "<b>Status:</b> "
+msgstr "<b>Status:</b>"
+
+#: ../../../src/ui.cpp:1256
+msgid ", has not been successfully broadcast yet"
+msgstr ", nie został jeszcze prawidłowo rozgłoszony"
+
+#: ../../../src/ui.cpp:1258
+#, c-format
+msgid ", broadcast through %d node"
+msgstr ", rozgłasza przez %d węzeł"
+
+#: ../../../src/ui.cpp:1260
+#, c-format
+msgid ", broadcast through %d nodes"
+msgstr ", rozgłasza przez %d węzłów"
+
+#: ../../../src/ui.cpp:1264
+msgid "<b>Date:</b> "
+msgstr "<b>Data:</b>"
+
+#: ../../../src/ui.cpp:1272
+msgid "<b>Source:</b> Generated<br>"
+msgstr "<b>Źródło:</b> Wygenerowano<br>"
+
+#: ../../../src/ui.cpp:1278
+#: ../../../src/ui.cpp:1296
+msgid "<b>From:</b> "
+msgstr "<b>Od:</b>"
+
+#: ../../../src/ui.cpp:1296
+msgid "unknown"
+msgstr "nieznany"
+
+#: ../../../src/ui.cpp:1297
+#: ../../../src/ui.cpp:1321
+#: ../../../src/ui.cpp:1380
+msgid "<b>To:</b> "
+msgstr "<b>Do:</b>"
+
+#: ../../../src/ui.cpp:1300
+msgid " (yours, label: "
+msgstr " (twoja, etykieta: "
+
+#: ../../../src/ui.cpp:1302
+msgid " (yours)"
+msgstr " (twoja)"
+
+#: ../../../src/ui.cpp:1339
+#: ../../../src/ui.cpp:1351
+#: ../../../src/ui.cpp:1397
+#: ../../../src/ui.cpp:1414
+msgid "<b>Credit:</b> "
+msgstr "<b>Suma:</b>"
+
+#: ../../../src/ui.cpp:1341
+#, c-format
+msgid "(%s matures in %d more blocks)"
+msgstr "(%s dojrzałych w %d więcej bloków)"
+
+#: ../../../src/ui.cpp:1343
+msgid "(not accepted)"
+msgstr "(nie zaakceptowano)"
+
+#: ../../../src/ui.cpp:1388
+#: ../../../src/ui.cpp:1396
+#: ../../../src/ui.cpp:1411
+msgid "<b>Debit:</b> "
+msgstr "<b>Obciążenie:</b>"
+
+#: ../../../src/ui.cpp:1402
+msgid "<b>Transaction fee:</b> "
+msgstr "<b>Prowizja transakcji:</b>"
+
+#: ../../../src/ui.cpp:1418
+msgid "<b>Net amount:</b> "
+msgstr "<b>Kwota netto:</b>"
+
+#: ../../../src/ui.cpp:1425
+msgid "Message:"
+msgstr "Wiadomość:"
+
+#: ../../../src/ui.cpp:1427
+msgid "Comment:"
+msgstr "Komentarz:"
+
+#: ../../../src/ui.cpp:1430
+msgid "Generated coins must wait 120 blocks before they can be spent.  When you generated this block, it was broadcast to the network to be added to the block chain.  If it fails to get into the chain, it will change to \"not accepted\" and not be spendable.  This may occasionally happen if another node generates a block within a few seconds of yours."
+msgstr "Wygenerowane monety muszą poczekać 120 bloków zanim mogą zostać wydane. Gdy wygenerowałeś ten blok, został rozgłoszony do sieci z przeznaczeniem do dodania do łańcucha bloków. Jeżeli nie uda się dodać bloku do łańcucha, zostanie oznaczony jako \"nie zaakceptowany\" i nie będzie mógł zostać wydany. Sporadycznie dzieje się tak jeżeli inny węzeł wygeneruje blok nie dalej niż kilka sekund od ciebie."
+
+#: ../../../src/ui.cpp:1610
+msgid "Cannot write autostart/bitcoin.desktop file"
+msgstr "Nie mogę zapisać pliku autostart/bitcoin.desktop"
+
+#: ../../../src/ui.cpp:1646
+msgid "Main"
+msgstr "Główne"
+
+#: ../../../src/ui.cpp:1656
+msgid "&Start Bitcoin on window system startup"
+msgstr "&Uruchom Bitcoin przy starcie systemu"
+
+#: ../../../src/ui.cpp:1663
+msgid "&Minimize on close"
+msgstr "&Minimalizuj przy zamknięciu"
+
+#: ../../../src/ui.cpp:1805
+#, c-format
+msgid "version %s"
+msgstr "wersja %s"
+
+#: ../../../src/ui.cpp:1928
+msgid "Error in amount  "
+msgstr "Nieprawidłowa kwota"
+
+#: ../../../src/ui.cpp:1928
+#: ../../../src/ui.cpp:1933
+#: ../../../src/ui.cpp:1938
+#: ../../../src/ui.cpp:1973
+#: ../../../src/uibase.cpp:55
+msgid "Send Coins"
+msgstr "Wyślij Monety"
+
+#: ../../../src/ui.cpp:1933
+msgid "Amount exceeds your balance  "
+msgstr "Kwota przekracza twój stan konta"
+
+#: ../../../src/ui.cpp:1938
+msgid "Total exceeds your balance when the "
+msgstr "Przekroczenie twojego stanu konta gdy"
+
+#: ../../../src/ui.cpp:1938
+msgid " transaction fee is included  "
+msgstr " prowizja jest wliczona"
+
+#: ../../../src/ui.cpp:1956
+msgid "Payment sent  "
+msgstr "Wysłano płatność"
+
+#: ../../../src/ui.cpp:1956
+#: ../../../src/ui.cpp:1961
+#: ../../../src/ui.cpp:2107
+#: ../../../src/ui.cpp:2260
+#: ../../../src/wallet.cpp:924
+msgid "Sending..."
+msgstr "Wysyłanie..."
+
+#: ../../../src/ui.cpp:1973
+msgid "Invalid address  "
+msgstr "Nieprawidłowy adres"
+
+#: ../../../src/ui.cpp:2028
+#, c-format
+msgid "Sending %s to %s"
+msgstr "Wysyłanie %s do %s"
+
+#: ../../../src/ui.cpp:2101
+#: ../../../src/ui.cpp:2134
+msgid "CANCELLED"
+msgstr "ANULOWANO"
+
+#: ../../../src/ui.cpp:2105
+msgid "Cancelled"
+msgstr "Anulowano"
+
+#: ../../../src/ui.cpp:2107
+msgid "Transfer cancelled  "
+msgstr "Transfer anulowano"
+
+#: ../../../src/ui.cpp:2160
+msgid "Error: "
+msgstr "Błąd:"
+
+#: ../../../src/ui.cpp:2174
+#: ../../../src/ui.cpp:2245
+#: ../../../src/wallet.cpp:943
+msgid "Insufficient funds"
+msgstr "Niewystarczające fundusze"
+
+#: ../../../src/ui.cpp:2179
+msgid "Connecting..."
+msgstr "Łączenie..."
+
+#: ../../../src/ui.cpp:2184
+msgid "Unable to connect"
+msgstr "Nie można połączyć"
+
+#: ../../../src/ui.cpp:2189
+msgid "Requesting public key..."
+msgstr "Żądanie klucza publicznego..."
+
+#: ../../../src/ui.cpp:2201
+msgid "Received public key..."
+msgstr "Otrzymano klucz publiczny..."
+
+#: ../../../src/ui.cpp:2215
+msgid "Recipient is not accepting transactions sent by IP address"
+msgstr "Adresat nie akceptuje transakcji wysyłanych przez adres IP"
+
+#: ../../../src/ui.cpp:2217
+msgid "Transfer was not accepted"
+msgstr "Transfer nie został zaakceptowany"
+
+#: ../../../src/ui.cpp:2226
+msgid "Invalid response received"
+msgstr "Otrzymano niepoprawną odpowiedź"
+
+#: ../../../src/ui.cpp:2241
+msgid "Creating transaction..."
+msgstr "Tworzenie transakcji..."
+
+#: ../../../src/ui.cpp:2253
+#, c-format
+msgid "This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"
+msgstr "Ta transakcja wymaga prowizji co najmniej %s z uwagi na kwotę, złożoność lub użycie niedawno otrzymanych funduszy"
+
+#: ../../../src/ui.cpp:2255
+msgid "Transaction creation failed"
+msgstr "Błąd tworzenia transakcji "
+
+#: ../../../src/ui.cpp:2262
+msgid "Transaction aborted"
+msgstr "Transakcję przerwano"
+
+#: ../../../src/ui.cpp:2270
+msgid "Lost connection, transaction cancelled"
+msgstr "Utracono połączenie, transakcja anulowana"
+
+#: ../../../src/ui.cpp:2286
+msgid "Sending payment..."
+msgstr "Wysyłanie płatności..."
+
+#: ../../../src/ui.cpp:2292
+msgid "The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."
+msgstr "Transakcja została odrzucona. Może się tak zdarzyć jeżeli część monet w twoim portfelu zostało wydanych, np. gdy użyto kopii pliku wallet.dat i monety zostały wydane w kopii, a tutaj nie zostały oznaczone jako wydane."
+
+#: ../../../src/ui.cpp:2301
+msgid "Waiting for confirmation..."
+msgstr "Oczekiwanie na potwierdzenie..."
+
+#: ../../../src/ui.cpp:2319
+msgid ""
+"The payment was sent, but the recipient was unable to verify it.\n"
+"The transaction is recorded and will credit to the recipient,\n"
+"but the comment information will be blank."
+msgstr ""
+"Płatność została wysłana, ale odbiorca nie mógł jej zweryfikować.\n"
+"Transakcja została zarejestrowana i zostanie przypisana do odbiorcy,\n"
+"ale informacja w komentarzu będzie pusta."
+
+#: ../../../src/ui.cpp:2328
+msgid "Payment was sent, but an invalid response was received"
+msgstr "Płatność została wysłana, ale otrzymano nieprawidłową odpowiedź"
+
+#: ../../../src/ui.cpp:2334
+msgid "Payment completed"
+msgstr "Płatność zakończona"
+
+#: ../../../src/ui.cpp:2376
+#: ../../../src/ui.cpp:2522
+#: ../../../src/ui.cpp:2559
+msgid "Name"
+msgstr "Nazwa"
+
+#: ../../../src/ui.cpp:2377
+#: ../../../src/ui.cpp:2522
+#: ../../../src/ui.cpp:2559
+msgid "Address"
+msgstr "Adres"
+
+#: ../../../src/ui.cpp:2379
+#: ../../../src/ui.cpp:2534
+msgid "Label"
+msgstr "Etykieta"
+
+#: ../../../src/ui.cpp:2380
+#: ../../../src/uibase.cpp:837
+msgid "Bitcoin Address"
+msgstr "Adres Bitcoin"
+
+#: ../../../src/ui.cpp:2504
+msgid "This is one of your own addresses for receiving payments and cannot be entered in the address book.  "
+msgstr "To jest jeden z twoich adresów na otrzymywane płatności i nie może zostać wpisany do księgi adresowej."
+
+#: ../../../src/ui.cpp:2522
+#: ../../../src/ui.cpp:2528
+msgid "Edit Address"
+msgstr "Edytuj Adres"
+
+#: ../../../src/ui.cpp:2534
+msgid "Edit Address Label"
+msgstr "Edytuj Etykietę Adresu"
+
+#: ../../../src/ui.cpp:2559
+#: ../../../src/ui.cpp:2565
+msgid "Add Address"
+msgstr "Dodaj Adres"
+
+#: ../../../src/ui.cpp:2642
+msgid "Bitcoin"
+msgstr "Bitcoin"
+
+#: ../../../src/ui.cpp:2644
+msgid "Bitcoin - Generating"
+msgstr "Bitcoin - Generowanie"
+
+#: ../../../src/ui.cpp:2646
+msgid "Bitcoin - (not connected)"
+msgstr "Bitcoin - (nie połączony)"
+
+#: ../../../src/ui.cpp:2725
+msgid "&Open Bitcoin"
+msgstr "&Otwórz Bitcoin"
+
+#: ../../../src/ui.cpp:2726
+msgid "&Send Bitcoins"
+msgstr "&Wyślij Bitcoiny"
+
+#: ../../../src/ui.cpp:2727
+msgid "O&ptions..."
+msgstr "O&pcje..."
+
+#: ../../../src/ui.cpp:2730
+#: ../../../src/uibase.cpp:25
+msgid "E&xit"
+msgstr "W&yjście"
+
+#: ../../../src/ui.cpp:2956
+msgid "Program has crashed and will terminate.  "
+msgstr "Program uległ awarii i zostanie przerwany."
+
+#: ../../../src/main.cpp:1430
+msgid "Warning: Disk space is low  "
+msgstr "Ostrzeżenie: Mało miejsca na dysku"
+
+#: ../../../src/uibase.cpp:28
+msgid "&File"
+msgstr "&Plik"
+
+#: ../../../src/uibase.cpp:32
+msgid "&Your Receiving Addresses..."
+msgstr "&Twój Adres Odbiorczy..."
+
+#: ../../../src/uibase.cpp:36
+msgid "&Options..."
+msgstr "&Opcje..."
+
+#: ../../../src/uibase.cpp:39
+msgid "&Settings"
+msgstr "&Ustawienia"
+
+#: ../../../src/uibase.cpp:43
+msgid "&About..."
+msgstr "&O programie..."
+
+#: ../../../src/uibase.cpp:46
+msgid "&Help"
+msgstr "&Pomoc"
+
+#: ../../../src/uibase.cpp:56
+msgid "Address Book"
+msgstr "Księga Adresowa"
+
+#: ../../../src/uibase.cpp:69
+msgid "Your Bitcoin Address:"
+msgstr "Twój Adres Bitcoin:"
+
+#: ../../../src/uibase.cpp:76
+msgid " &New... "
+msgstr " &Nowy..."
+
+#: ../../../src/uibase.cpp:79
+#: ../../../src/uibase.cpp:780
+#: ../../../src/uibase.cpp:883
+msgid " &Copy to Clipboard "
+msgstr " &Kopiuj do schowka "
+
+#: ../../../src/uibase.cpp:93
+msgid "Balance:"
+msgstr "Saldo:"
+
+#: ../../../src/uibase.cpp:109
+msgid " All"
+msgstr " Wszystko"
+
+#: ../../../src/uibase.cpp:109
+msgid " Sent"
+msgstr "Wysłano"
+
+#: ../../../src/uibase.cpp:109
+msgid " Received"
+msgstr "Otrzymano"
+
+#: ../../../src/uibase.cpp:109
+msgid " In Progress"
+msgstr "W Trakcie"
+
+#: ../../../src/uibase.cpp:130
+msgid "All Transactions"
+msgstr "Wszystkie Transakcje"
+
+#: ../../../src/uibase.cpp:141
+msgid "Sent/Received"
+msgstr "Wysłano/Otrzymano"
+
+#: ../../../src/uibase.cpp:152
+msgid "Sent"
+msgstr "Wysłano"
+
+#: ../../../src/uibase.cpp:163
+msgid "Received"
+msgstr "Otrzymano"
+
+#: ../../../src/uibase.cpp:302
+#: ../../../src/uibase.cpp:443
+#: ../../../src/uibase.cpp:542
+#: ../../../src/uibase.cpp:722
+#: ../../../src/uibase.cpp:783
+#: ../../../src/uibase.cpp:892
+#: ../../../src/uibase.cpp:981
+msgid "OK"
+msgstr "OK"
+
+#: ../../../src/uibase.cpp:345
+msgid "&Start Bitcoin on system startup"
+msgstr "&Uruchom Bitcoin wraz ze startem systemu"
+
+#: ../../../src/uibase.cpp:348
+msgid "&Minimize to the tray instead of the taskbar"
+msgstr "&Zminimalizuj do traya zamiast do paska zadań"
+
+#: ../../../src/uibase.cpp:351
+msgid "Map port using &UPnP"
+msgstr "Mapuj port używając &UPnP"
+
+#: ../../../src/uibase.cpp:354
+msgid "M&inimize to the tray on close"
+msgstr "Zm&inimalizuj do traya przy zamknięciu"
+
+#: ../../../src/uibase.cpp:360
+msgid "&Connect through socks4 proxy: "
+msgstr "&Połącz przez socks4 proxy:"
+
+#: ../../../src/uibase.cpp:371
+msgid "Proxy &IP:"
+msgstr "Proxy &IP:"
+
+#: ../../../src/uibase.cpp:379
+msgid " &Port:"
+msgstr " &Port:"
+
+#: ../../../src/uibase.cpp:392
+msgid "Optional transaction fee per KB that helps make sure your transactions are processed quickly.  Most transactions are 1KB.  Fee 0.01 recommended."
+msgstr "Opcjonalna prowizja określona dla KB transakcji, która zapewni, że twoje transakcje będą szybko przetworzone. Większość transakcji to 1KB. Rekomendowana prowizja to 0.01."
+
+#: ../../../src/uibase.cpp:399
+msgid "Pay transaction fee:"
+msgstr "Płać prowizję transakcji:"
+
+#: ../../../src/uibase.cpp:420
+msgid "// [don't translate] Test panel 2 for future expansion"
+msgstr ""
+
+#: ../../../src/uibase.cpp:424
+msgid "// [don't translate] Let's not start multiple pages until the first page is filled up"
+msgstr ""
+
+#: ../../../src/uibase.cpp:446
+#: ../../../src/uibase.cpp:668
+#: ../../../src/uibase.cpp:727
+#: ../../../src/uibase.cpp:786
+#: ../../../src/uibase.cpp:895
+#: ../../../src/uibase.cpp:984
+msgid "Cancel"
+msgstr "Anuluj"
+
+#: ../../../src/uibase.cpp:449
+msgid "&Apply"
+msgstr "&Zastosuj"
+
+#: ../../../src/uibase.cpp:508
+msgid "Bitcoin "
+msgstr "Bitcoin"
+
+#: ../../../src/uibase.cpp:514
+msgid "version"
+msgstr "wersja"
+
+#: ../../../src/uibase.cpp:525
+msgid ""
+"Copyright (c) 2009-2011 Bitcoin Developers\n"
+"\n"
+"This is experimental software.\n"
+"\n"
+"Distributed under the MIT/X11 software license, see the accompanying file \n"
+"license.txt or http://www.opensource.org/licenses/mit-license.php.\n"
+"\n"
+"This product includes software developed by the OpenSSL Project for use in the \n"
+"OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by \n"
+"Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard."
+msgstr ""
+"Copyright (c) 2009-2011 Bitcoin Developers\n"
+"\n"
+"To oprogramowanie jest eksperymentalne.\n"
+"\n"
+"Dystrybuowane na licencji MIT/X11, zobacz towarzyszący plik \n"
+"license.txt lub http://www.opensource.org/licenses/mit-license.php.\n"
+"\n"
+"Ten produkt zawiera oprogramowanie rozwijane przez OpenSSL Project w \n"
+"OpenSSL Toolkit (http://www.openssl.org/) i oprogramowanie kryptograficzne napisane przez \n"
+"Erica Younga (eay@cryptsoft.com) oraz oprogramowanie UPnP napisane przez Thomasa Bernarda."
+
+#: ../../../src/uibase.cpp:581
+msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
+msgstr "Wprowadź adres Bitcoin (np. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
+
+#: ../../../src/uibase.cpp:595
+msgid "Pay &To:"
+msgstr "Wpłać &Dla:"
+
+#: ../../../src/uibase.cpp:610
+msgid "&Paste"
+msgstr "&Wklej"
+
+#: ../../../src/uibase.cpp:613
+msgid " Address &Book..."
+msgstr " Księga &Adresowa..."
+
+#: ../../../src/uibase.cpp:620
+msgid "&Amount:"
+msgstr "&Kwota:"
+
+#: ../../../src/uibase.cpp:630
+msgid "T&ransfer:"
+msgstr "T&ransfer:"
+
+#: ../../../src/uibase.cpp:636
+msgid " Standard"
+msgstr " Standard"
+
+#: ../../../src/uibase.cpp:663
+msgid "&Send"
+msgstr "&Wyślij"
+
+#: ../../../src/uibase.cpp:711
+msgid ""
+"\n"
+"\n"
+"Connecting..."
+msgstr ""
+"\n"
+"\n"
+"Łączenie..."
+
+#: ../../../src/uibase.cpp:761
+msgid "These are your Bitcoin addresses for receiving payments.  You may want to give a different one to each sender so you can keep track of who is paying you.  The highlighted address is displayed in the main window."
+msgstr "To są twoje adresy Bitcoin dla otrzymywania płatności. Możesz chcieć podać różne dla każdego płacącego aby kontrolować kto ci płaci. Wyróżniony adres będzie wyświetlany w oknie głównym."
+
+#: ../../../src/uibase.cpp:774
+#: ../../../src/uibase.cpp:886
+msgid "&Edit..."
+msgstr "&Edytuj..."
+
+#: ../../../src/uibase.cpp:777
+#: ../../../src/uibase.cpp:889
+msgid " &New Address... "
+msgstr " &Nowy Adres..."
+
+#: ../../../src/uibase.cpp:849
+msgid "Sending"
+msgstr "Wysyłanie"
+
+#: ../../../src/uibase.cpp:857
+msgid "These are your Bitcoin addresses for receiving payments.  You can give a different one to each sender to keep track of who is paying you.  The highlighted address will be displayed in the main window."
+msgstr "To są twoje adresy Bitcoin dla otrzymywania płatności. Możesz podać różne dla każdego płacącego aby kontrolować kto ci płaci. Wyróżniony adres będzie wyświetlany w oknie głównym."
+
+#: ../../../src/uibase.cpp:870
+msgid "Receiving"
+msgstr "Otrzymywanie"
+
+#: ../../../src/uibase.cpp:880
+msgid "&Delete"
+msgstr "&Usuń"
+
+#: ../../../src/wallet.cpp:917
+#, c-format
+msgid "Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds  "
+msgstr "Błąd: Ta transakcja wymaga prowizji co najmniej %s z uwagi na kwotę, złożoność lub użycie niedawno otrzymanych funduszy"
+
+#: ../../../src/wallet.cpp:919
+msgid "Error: Transaction creation failed  "
+msgstr "Błąd: Nie udało się utworzyć transakcji"
+
+#: ../../../src/wallet.cpp:928
+msgid "Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."
+msgstr "Błąd: Transakcja została odrzucona. Może się tak zdarzyć jeżeli część monet w twoim portfelu zostało wydanych, np. gdy użyto kopii pliku wallet.dat i monety zostały wydane w kopii, a tutaj nie zostały oznaczone jako wydane."
+
+#: ../../../src/wallet.cpp:941
+msgid "Invalid amount"
+msgstr "Niewłaściwa kwota"
+
+#: ../../../src/wallet.cpp:948
+msgid "Invalid bitcoin address"
+msgstr "Niewłaściwy adres bitcoin"
+
+#: ../../../src/uibase.h:147
+msgid "Transaction Details"
+msgstr "Szczegóły Transakcji"
+
+#: ../../../src/uibase.h:199
+msgid "Options"
+msgstr "Opcje"
+
+#: ../../../src/uibase.h:228
+msgid "About Bitcoin"
+msgstr "O Bitcoin"
+
+#: ../../../src/uibase.h:337
+msgid "Your Bitcoin Addresses"
+msgstr "Twoje Adresy Bitcoin"
+
index 1b502fa..92bb888 100644 (file)
Binary files a/locale/ru/LC_MESSAGES/bitcoin.mo and b/locale/ru/LC_MESSAGES/bitcoin.mo differ
index 0aa3173..d53b08d 100644 (file)
@@ -521,8 +521,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "Внимание: пожалуйста, проверьте дату и время на вашем компьютере. Если часы идут неверно, Bitcoin не будет работать правильно."
 
 #: ../../../src/util.cpp:898
-msgid "-beta"
-msgstr "-beta"
+msgid "beta"
+msgstr "beta"
 
 #: ../../../src/uibase.cpp:28
 msgid "&File"
@@ -703,7 +703,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "Введите адрес Bitcoin (напр. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "Введите адрес Bitcoin (напр. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -773,10 +773,6 @@ msgstr "Получение"
 msgid "&Delete"
 msgstr "&Удалить"
 
-#: ../../../src/init.cpp:145
-msgid " beta"
-msgstr " beta"
-
 #: ../../../src/init.cpp:147
 msgid "Bitcoin version"
 msgstr "Bitcoin версия"
index 0c50c0b..87538f0 100644 (file)
Binary files a/locale/zh_cn/LC_MESSAGES/bitcoin.mo and b/locale/zh_cn/LC_MESSAGES/bitcoin.mo differ
index 338e666..e870a16 100644 (file)
@@ -17,10 +17,6 @@ msgstr ""
 "X-Poedit-Bookmarks: 77,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"
 "X-Poedit-SearchPath-0: ../../..\n"
 
-#: ../../../src/init.cpp:140
-msgid " beta"
-msgstr " 测试版"
-
 #: ../../../src/init.cpp:142
 msgid "Bitcoin version"
 msgstr "Bitcoin 版本"
@@ -876,7 +872,7 @@ msgstr ""
 
 #: ../../../src/uibase.cpp:581
 msgid "Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
-msgstr "输入 Bitcoin 地址 (比如 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L)"
+msgstr "输入 Bitcoin 地址 (比如 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"
 
 #: ../../../src/uibase.cpp:595
 msgid "Pay &To:"
@@ -951,8 +947,8 @@ msgid "Warning: Please check that your computer's date and time are correct.  If
 msgstr "警告: 请检查您的电脑日期和时间是否正确。 如果您的时钟不正确 Bitcoin 将无法正常工作。"
 
 #: ../../../src/util.cpp:899
-msgid "-beta"
-msgstr "-测试版"
+msgid "beta"
+msgstr "测试版"
 
 #: ../../../src/uibase.h:147
 msgid "Transaction Details"
@@ -969,49 +965,3 @@ msgstr "关于 Bitcoin"
 #: ../../../src/uibase.h:337
 msgid "Your Bitcoin Addresses"
 msgstr "您的 Bitcoin 地址"
-
-#~ msgid ""
-#~ "Error: This is an oversized transaction that requires a transaction fee "
-#~ "of %s  "
-#~ msgstr ""
-#~ "错误: 交易额过大,需要交易佣金 "
-#~ "%s  "
-
-#~ msgid "version %s%s BETA"
-#~ msgstr "版本 %s%s BETA"
-
-#~ msgid "n/a"
-#~ msgstr "n/a"
-
-#~ msgid "Can't include a message when sending to a Bitcoin address"
-#~ msgstr "发送到 Bitcoin 地址时无法包含信息"
-
-#~ msgid ""
-#~ "Optional transaction fee you give to the nodes that process your "
-#~ "transactions."
-#~ msgstr ""
-#~ "可选择向处理您交易的节点支付交易佣金。"
-
-#~ msgid "&Limit coin generation to"
-#~ msgstr "限制货币生成(&L)"
-
-#~ msgid "processors"
-#~ msgstr "处理器"
-
-#~ msgid "&From:"
-#~ msgstr "来自(&F):"
-
-#~ msgid "&Message:"
-#~ msgstr "信息(&M):"
-
-#~ msgid ""
-#~ "It's good policy to use a new address for each payment you receive.\n"
-#~ "\n"
-#~ "Label"
-#~ msgstr ""
-#~ "最好能为您收到的每次付款使用不同的地址。\n"
-#~ "\n"
-#~ "标签"
-
-#~ msgid "Will appear as \"From: Unknown\""
-#~ msgstr "将显示为“来自: 未知”"
index 2fa4d17..8677d33 100644 (file)
@@ -4,7 +4,7 @@ RequestExecutionLevel highest
 \r
 # General Symbol Definitions\r
 !define REGKEY "SOFTWARE\$(^Name)"\r
-!define VERSION 0.3.23\r
+!define VERSION 0.3.24\r
 !define COMPANY "Bitcoin project"\r
 !define URL http://www.bitcoin.org/\r
 \r
@@ -39,12 +39,12 @@ Var StartMenuGroup
 !insertmacro MUI_LANGUAGE English\r
 \r
 # Installer attributes\r
-OutFile bitcoin-0.3.23-win32-setup.exe\r
+OutFile bitcoin-0.3.24-win32-setup.exe\r
 InstallDir $PROGRAMFILES\Bitcoin\r
 CRCCheck on\r
 XPStyle on\r
 ShowInstDetails show\r
-VIProductVersion 0.3.23.0\r
+VIProductVersion 0.3.24.0\r
 VIAddVersionKey ProductName Bitcoin\r
 VIAddVersionKey ProductVersion "${VERSION}"\r
 VIAddVersionKey CompanyName "${COMPANY}"\r
index c2c239d..f044355 100644 (file)
@@ -3,12 +3,14 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "db.h"
+#include "net.h"
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 
 using namespace std;
 using namespace boost;
 
-void ThreadFlushWalletDB(void* parg);
-
 
 unsigned int nWalletDBUpdated;
 uint64 nAccountingEntryNumber = 0;
@@ -147,7 +149,7 @@ void CDB::Close()
         --mapFileUseCount[strFile];
 }
 
-void CloseDb(const string& strFile)
+void static CloseDb(const string& strFile)
 {
     CRITICAL_BLOCK(cs_db)
     {
@@ -356,7 +358,7 @@ bool CTxDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
     return Write(string("bnBestInvalidWork"), bnBestInvalidWork);
 }
 
-CBlockIndex* InsertBlockIndex(uint256 hash)
+CBlockIndex static * InsertBlockIndex(uint256 hash)
 {
     if (hash == 0)
         return NULL;
@@ -581,8 +583,19 @@ bool LoadAddresses()
 // CWalletDB
 //
 
-static set<int64> setKeyPool;
-static CCriticalSection cs_setKeyPool;
+bool CWalletDB::WriteName(const string& strAddress, const string& strName)
+{
+    nWalletDBUpdated++;
+    return Write(make_pair(string("name"), strAddress), strName);
+}
+
+bool CWalletDB::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.
+    nWalletDBUpdated++;
+    return Erase(make_pair(string("name"), strAddress));
+}
 
 bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
 {
@@ -657,9 +670,9 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin
 }
 
 
-bool CWalletDB::LoadWallet()
+bool CWalletDB::LoadWallet(CWallet* pwallet)
 {
-    vchDefaultKey.clear();
+    pwallet->vchDefaultKey.clear();
     int nFileVersion = 0;
     vector<uint256> vWalletUpgrade;
 
@@ -671,8 +684,8 @@ bool CWalletDB::LoadWallet()
 #endif
 
     //// todo: shouldn't we catch exceptions and try to recover and continue?
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(pwallet->cs_mapWallet)
+    CRITICAL_BLOCK(pwallet->cs_mapKeys)
     {
         // Get cursor
         Dbc* pcursor = GetCursor();
@@ -699,14 +712,15 @@ bool CWalletDB::LoadWallet()
             {
                 string strAddress;
                 ssKey >> strAddress;
-                ssValue >> mapAddressBook[strAddress];
+                ssValue >> pwallet->mapAddressBook[strAddress];
             }
             else if (strType == "tx")
             {
                 uint256 hash;
                 ssKey >> hash;
-                CWalletTx& wtx = mapWallet[hash];
+                CWalletTx& wtx = pwallet->mapWallet[hash];
                 ssValue >> wtx;
+                wtx.pwallet = pwallet;
 
                 if (wtx.GetHash() != hash)
                     printf("Error in wallet.dat, hash mismatch\n");
@@ -757,18 +771,18 @@ bool CWalletDB::LoadWallet()
                 else
                     ssValue >> wkey;
 
-                mapKeys[vchPubKey] = wkey.vchPrivKey;
+                pwallet->mapKeys[vchPubKey] = wkey.vchPrivKey;
                 mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
             }
             else if (strType == "defaultkey")
             {
-                ssValue >> vchDefaultKey;
+                ssValue >> pwallet->vchDefaultKey;
             }
             else if (strType == "pool")
             {
                 int64 nIndex;
                 ssKey >> nIndex;
-                setKeyPool.insert(nIndex);
+                pwallet->setKeyPool.insert(nIndex);
             }
             else if (strType == "version")
             {
@@ -800,7 +814,7 @@ bool CWalletDB::LoadWallet()
     }
 
     BOOST_FOREACH(uint256 hash, vWalletUpgrade)
-        WriteTx(hash, mapWallet[hash]);
+        WriteTx(hash, pwallet->mapWallet[hash]);
 
     printf("nFileVersion = %d\n", nFileVersion);
     printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
@@ -828,36 +842,9 @@ bool CWalletDB::LoadWallet()
     return true;
 }
 
-bool LoadWallet(bool& fFirstRunRet)
-{
-    fFirstRunRet = false;
-    if (!CWalletDB("cr+").LoadWallet())
-        return false;
-    fFirstRunRet = vchDefaultKey.empty();
-
-    if (mapKeys.count(vchDefaultKey))
-    {
-        // Set keyUser
-        keyUser.SetPubKey(vchDefaultKey);
-        keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
-    }
-    else
-    {
-        // Create new keyUser and set as default key
-        RandAddSeedPerfmon();
-
-        CWalletDB walletdb;
-        vchDefaultKey = GetKeyFromKeyPool();
-        walletdb.WriteDefaultKey(vchDefaultKey);
-        walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
-    }
-
-    CreateThread(ThreadFlushWalletDB, NULL);
-    return true;
-}
-
 void ThreadFlushWalletDB(void* parg)
 {
+    const string& strFile = ((const string*)parg)[0];
     static bool fOneThread;
     if (fOneThread)
         return;
@@ -893,7 +880,6 @@ void ThreadFlushWalletDB(void* parg)
 
                 if (nRefCount == 0 && !fShutdown)
                 {
-                    string strFile = "wallet.dat";
                     map<string, int>::iterator mi = mapFileUseCount.find(strFile);
                     if (mi != mapFileUseCount.end())
                     {
@@ -916,26 +902,27 @@ void ThreadFlushWalletDB(void* parg)
     }
 }
 
-void BackupWallet(const string& strDest)
+bool BackupWallet(const CWallet& wallet, const string& strDest)
 {
+    if (!wallet.fFileBacked)
+        return false;
     while (!fShutdown)
     {
         CRITICAL_BLOCK(cs_db)
         {
-            const string strFile = "wallet.dat";
-            if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
+            if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
             {
                 // Flush log data to the dat file
-                CloseDb(strFile);
+                CloseDb(wallet.strWalletFile);
                 dbenv.txn_checkpoint(0, 0, 0);
-                dbenv.lsn_reset(strFile.c_str(), 0);
-                mapFileUseCount.erase(strFile);
+                dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
+                mapFileUseCount.erase(wallet.strWalletFile);
 
                 // Copy wallet.dat
-                filesystem::path pathSrc(GetDataDir() + "/" + strFile);
+                filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
                 filesystem::path pathDest(strDest);
                 if (filesystem::is_directory(pathDest))
-                    pathDest = pathDest / strFile;
+                    pathDest = pathDest / wallet.strWalletFile;
 #if BOOST_VERSION >= 104000
                 filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
 #else
@@ -943,83 +930,10 @@ void BackupWallet(const string& strDest)
 #endif
                 printf("copied wallet.dat to %s\n", pathDest.string().c_str());
 
-                return;
+                return true;
             }
         }
         Sleep(100);
     }
-}
-
-
-void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
-{
-    nIndex = -1;
-    keypool.vchPubKey.clear();
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_setKeyPool)
-    {
-        // Top up key pool
-        int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
-        while (setKeyPool.size() < nTargetSize+1)
-        {
-            int64 nEnd = 1;
-            if (!setKeyPool.empty())
-                nEnd = *(--setKeyPool.end()) + 1;
-            if (!Write(make_pair(string("pool"), nEnd), CKeyPool(GenerateNewKey())))
-                throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
-            setKeyPool.insert(nEnd);
-            printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
-        }
-
-        // Get the oldest key
-        assert(!setKeyPool.empty());
-        nIndex = *(setKeyPool.begin());
-        setKeyPool.erase(setKeyPool.begin());
-        if (!Read(make_pair(string("pool"), nIndex), keypool))
-            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
-        if (!mapKeys.count(keypool.vchPubKey))
-            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
-        assert(!keypool.vchPubKey.empty());
-        printf("keypool reserve %"PRI64d"\n", nIndex);
-    }
-}
-
-void CWalletDB::KeepKey(int64 nIndex)
-{
-    // Remove from key pool
-    CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        Erase(make_pair(string("pool"), nIndex));
-    }
-    printf("keypool keep %"PRI64d"\n", nIndex);
-}
-
-void CWalletDB::ReturnKey(int64 nIndex)
-{
-    // Return to key pool
-    CRITICAL_BLOCK(cs_setKeyPool)
-        setKeyPool.insert(nIndex);
-    printf("keypool return %"PRI64d"\n", nIndex);
-}
-
-vector<unsigned char> GetKeyFromKeyPool()
-{
-    CWalletDB walletdb;
-    int64 nIndex = 0;
-    CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.KeepKey(nIndex);
-    return keypool.vchPubKey;
-}
-
-int64 GetOldestKeyPoolTime()
-{
-    CWalletDB walletdb;
-    int64 nIndex = 0;
-    CKeyPool keypool;
-    walletdb.ReserveKeyFromKeyPool(nIndex, keypool);
-    walletdb.ReturnKey(nIndex);
-    return keypool.nTime;
+    return false;
 }
index 9826194..b89b34e 100644 (file)
--- a/src/db.h
+++ b/src/db.h
 
 #include <db_cxx.h>
 
-class CTransaction;
 class CTxIndex;
 class CDiskBlockIndex;
 class CDiskTxPos;
 class COutPoint;
-class CUser;
-class CReview;
 class CAddress;
 class CWalletTx;
+class CWallet;
 class CAccount;
 class CAccountingEntry;
 class CBlockLocator;
 
-extern std::map<std::string, std::string> mapAddressBook;
-extern CCriticalSection cs_mapAddressBook;
-extern std::vector<unsigned char> vchDefaultKey;
-extern bool fClient;
-extern int nBestHeight;
-
 
 extern unsigned int nWalletDBUpdated;
 extern DbEnv dbenv;
 
 
 extern void DBFlush(bool fShutdown);
-extern std::vector<unsigned char> GetKeyFromKeyPool();
-extern int64 GetOldestKeyPoolTime();
+void ThreadFlushWalletDB(void* parg);
+bool BackupWallet(const CWallet& wallet, const std::string& strDest);
 
 
 
@@ -321,9 +313,6 @@ bool LoadAddresses();
 
 
 
-
-
-
 class CKeyPool
 {
 public:
@@ -356,7 +345,7 @@ public:
 class CWalletDB : public CDB
 {
 public:
-    CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode)
+    CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
     {
     }
 private:
@@ -369,23 +358,9 @@ public:
         return Read(std::make_pair(std::string("name"), strAddress), strName);
     }
 
-    bool WriteName(const std::string& strAddress, const std::string& strName)
-    {
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            mapAddressBook[strAddress] = strName;
-        nWalletDBUpdated++;
-        return Write(std::make_pair(std::string("name"), strAddress), strName);
-    }
+    bool WriteName(const std::string& strAddress, const std::string& strName);
 
-    bool EraseName(const std::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++;
-        return Erase(std::make_pair(std::string("name"), strAddress));
-    }
+    bool EraseName(const std::string& strAddress);
 
     bool ReadTx(uint256 hash, CWalletTx& wtx)
     {
@@ -435,11 +410,27 @@ public:
 
     bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
     {
-        vchDefaultKey = vchPubKey;
         nWalletDBUpdated++;
         return Write(std::string("defaultkey"), vchPubKey);
     }
 
+    bool ReadPool(int64 nPool, CKeyPool& keypool)
+    {
+        return Read(std::make_pair(std::string("pool"), nPool), keypool);
+    }
+
+    bool WritePool(int64 nPool, const CKeyPool& keypool)
+    {
+        nWalletDBUpdated++;
+        return Write(std::make_pair(std::string("pool"), nPool), keypool);
+    }
+
+    bool ErasePool(int64 nPool)
+    {
+        nWalletDBUpdated++;
+        return Erase(std::make_pair(std::string("pool"), nPool));
+    }
+
     template<typename T>
     bool ReadSetting(const std::string& strKey, T& value)
     {
@@ -459,68 +450,7 @@ public:
     int64 GetAccountCreditDebit(const std::string& strAccount);
     void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
 
-    bool LoadWallet();
-protected:
-    void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
-    void KeepKey(int64 nIndex);
-    static void ReturnKey(int64 nIndex);
-    friend class CReserveKey;
-    friend std::vector<unsigned char> GetKeyFromKeyPool();
-    friend int64 GetOldestKeyPoolTime();
-};
-
-bool LoadWallet(bool& fFirstRunRet);
-void BackupWallet(const std::string& strDest);
-
-inline bool SetAddressBookName(const std::string& strAddress, const std::string& strName)
-{
-    return CWalletDB().WriteName(strAddress, strName);
-}
-
-class CReserveKey
-{
-protected:
-    int64 nIndex;
-    std::vector<unsigned char> vchPubKey;
-public:
-    CReserveKey()
-    {
-        nIndex = -1;
-    }
-
-    ~CReserveKey()
-    {
-        if (!fShutdown)
-            ReturnKey();
-    }
-
-    std::vector<unsigned char> GetReservedKey()
-    {
-        if (nIndex == -1)
-        {
-            CKeyPool keypool;
-            CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool);
-            vchPubKey = keypool.vchPubKey;
-        }
-        assert(!vchPubKey.empty());
-        return vchPubKey;
-    }
-
-    void KeepKey()
-    {
-        if (nIndex != -1)
-            CWalletDB().KeepKey(nIndex);
-        nIndex = -1;
-        vchPubKey.clear();
-    }
-
-    void ReturnKey()
-    {
-        if (nIndex != -1)
-            CWalletDB::ReturnKey(nIndex);
-        nIndex = -1;
-        vchPubKey.clear();
-    }
+    bool LoadWallet(CWallet* pwallet);
 };
 
 #endif
index d40c5ed..d1844eb 100644 (file)
@@ -48,7 +48,6 @@
 #include <limits.h>
 #include <float.h>
 #include <assert.h>
-#include <memory>
 #include <iostream>
 #include <sstream>
 #include <string>
 #include <list>
 #include <deque>
 #include <map>
-#include <set>
-#include <algorithm>
-#include <numeric>
+
 #include <boost/foreach.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-#include <boost/tuple/tuple_io.hpp>
-#include <boost/array.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/thread.hpp>
-#include <boost/interprocess/sync/file_lock.hpp>
-#include <boost/interprocess/sync/interprocess_mutex.hpp>
-#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
-#include <boost/date_time/gregorian/gregorian_types.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/config.hpp>
-#include <boost/program_options/detail/config_file.hpp>
-#include <boost/program_options/parsers.hpp>
 
 #ifdef __WXMSW__
 #include <windows.h>
 
 #pragma hdrstop
 
-#include "strlcpy.h"
 #include "serialize.h"
 #include "uint256.h"
 #include "util.h"
-#include "key.h"
 #include "bignum.h"
 #include "base58.h"
-#include "script.h"
-#include "db.h"
-#include "net.h"
-#include "irc.h"
 #include "main.h"
-#include "rpc.h"
 #ifdef GUI
 #include "uibase.h"
 #include "ui.h"
 #else
 #include "noui.h"
 #endif
-#include "init.h"
 
 #ifdef GUI
 #include "xpm/addressbook16.xpm"
index a510460..635799c 100644 (file)
@@ -2,10 +2,20 @@
 // 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"
+#include "db.h"
+#include "rpc.h"
+#include "net.h"
+#include "init.h"
+#include "strlcpy.h"
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/interprocess/sync/file_lock.hpp>
 
 using namespace std;
 using namespace boost;
 
+CWallet* pwalletMain;
+
 //////////////////////////////////////////////////////////////////////////////
 //
 // Shutdown
@@ -38,6 +48,8 @@ void Shutdown(void* parg)
         StopNode();
         DBFlush(true);
         boost::filesystem::remove(GetPidFile());
+        UnregisterWallet(pwalletMain);
+        delete pwalletMain;
         CreateThread(ExitTimeout, NULL);
         Sleep(50);
         printf("Bitcoin exiting\n\n");
@@ -129,10 +141,19 @@ bool AppInit2(int argc, char* argv[])
 
     if (mapArgs.count("-datadir"))
     {
-        filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
-        strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
+        if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
+        {
+            filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
+            strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
+        }
+        else
+        {
+            fprintf(stderr, "Error: Specified directory does not exist\n");
+            Shutdown(NULL);
+        }
     }
 
+
     ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
 
     if (mapArgs.count("-?") || mapArgs.count("--help"))
@@ -151,6 +172,7 @@ bool AppInit2(int argc, char* argv[])
             "  -gen=0           \t\t  " + _("Don't generate coins\n") +
             "  -min             \t\t  " + _("Start minimized\n") +
             "  -datadir=<dir>   \t\t  " + _("Specify data directory\n") +
+            "  -timeout=<n>     \t  "   + _("Specify connection timeout (in milliseconds)\n") +
             "  -proxy=<ip:port> \t  "   + _("Connect through socks4 proxy\n") +
             "  -dns             \t  "   + _("Allow DNS lookups for addnode and connect\n") +
             "  -addnode=<ip>    \t  "   + _("Add a node to connect to\n") +
@@ -364,16 +386,19 @@ bool AppInit2(int argc, char* argv[])
     printf("Loading wallet...\n");
     nStart = GetTimeMillis();
     bool fFirstRun;
-    if (!LoadWallet(fFirstRun))
+    pwalletMain = new CWallet("wallet.dat");
+    if (!pwalletMain->LoadWallet(fFirstRun))
         strErrors += _("Error loading wallet.dat      \n");
     printf(" wallet      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
 
+    RegisterWallet(pwalletMain);
+
     CBlockIndex *pindexRescan = pindexBest;
     if (GetBoolArg("-rescan"))
         pindexRescan = pindexGenesisBlock;
     else
     {
-        CWalletDB walletdb;
+        CWalletDB walletdb("wallet.dat");
         CBlockLocator locator;
         if (walletdb.ReadBestBlock(locator))
             pindexRescan = locator.GetBlockIndex();
@@ -382,7 +407,7 @@ bool AppInit2(int argc, char* argv[])
     {
         printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
         nStart = GetTimeMillis();
-        ScanForWalletTransactions(pindexRescan, true);
+        pwalletMain->ScanForWalletTransactions(pindexRescan, true);
         printf(" rescan      %15"PRI64d"ms\n", GetTimeMillis() - nStart);
     }
 
@@ -391,10 +416,11 @@ bool AppInit2(int argc, char* argv[])
         //// debug print
         printf("mapBlockIndex.size() = %d\n",   mapBlockIndex.size());
         printf("nBestHeight = %d\n",            nBestHeight);
-        printf("mapKeys.size() = %d\n",         mapKeys.size());
+        printf("mapKeys.size() = %d\n",         pwalletMain->mapKeys.size());
+        printf("setKeyPool.size() = %d\n",      pwalletMain->setKeyPool.size());
         printf("mapPubKeys.size() = %d\n",      mapPubKeys.size());
-        printf("mapWallet.size() = %d\n",       mapWallet.size());
-        printf("mapAddressBook.size() = %d\n",  mapAddressBook.size());
+        printf("mapWallet.size() = %d\n",       pwalletMain->mapWallet.size());
+        printf("mapAddressBook.size() = %d\n",  pwalletMain->mapAddressBook.size());
 
     if (!strErrors.empty())
     {
@@ -403,7 +429,7 @@ bool AppInit2(int argc, char* argv[])
     }
 
     // Add wallet transactions that aren't already in a block to mapTransactions
-    ReacceptWalletTransactions();
+    pwalletMain->ReacceptWalletTransactions();
 
     //
     // Parameters
@@ -414,6 +440,13 @@ bool AppInit2(int argc, char* argv[])
         return false;
     }
 
+    if (mapArgs.count("-timeout"))
+    {
+        int nNewTimeout = GetArg("-timeout", 5000);
+        if (nNewTimeout > 0 && nNewTimeout < 600000)
+            nConnectTimeout = nNewTimeout;
+    }
+
     if (mapArgs.count("-printblock"))
     {
         string strMatch = mapArgs["-printblock"];
@@ -461,7 +494,9 @@ bool AppInit2(int argc, char* argv[])
         }
     }
 
-    if (mapArgs.count("-dnsseed"))
+    if (GetBoolArg("-nodnsseed"))
+        printf("DNS seeding disabled\n");
+    else
         DNSAddressSeed();
 
     if (mapArgs.count("-paytxfee"))
index 61b2728..a02260c 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef BITCOIN_INIT_H
 #define BITCOIN_INIT_H
 
+extern CWallet* pwalletMain;
+
 void Shutdown(void* parg);
 bool AppInit(int argc, char* argv[]);
 bool AppInit2(int argc, char* argv[]);
index a76374d..cde934e 100644 (file)
@@ -3,6 +3,9 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "irc.h"
+#include "net.h"
+#include "strlcpy.h"
 
 using namespace std;
 using namespace boost;
diff --git a/src/keystore.cpp b/src/keystore.cpp
new file mode 100644 (file)
index 0000000..7dd045f
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
+// 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"
+#include "db.h"
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// mapKeys
+//
+
+std::vector<unsigned char> CKeyStore::GenerateNewKey()
+{
+    RandAddSeedPerfmon();
+    CKey key;
+    key.MakeNewKey();
+    if (!AddKey(key))
+        throw std::runtime_error("GenerateNewKey() : AddKey failed");
+    return key.GetPubKey();
+}
+
+bool CKeyStore::AddKey(const CKey& key)
+{
+    CRITICAL_BLOCK(cs_mapKeys)
+    {
+        mapKeys[key.GetPubKey()] = key.GetPrivKey();
+        mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
+    }
+}
+
diff --git a/src/keystore.h b/src/keystore.h
new file mode 100644 (file)
index 0000000..6080d7d
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KEYSTORE_H
+#define BITCOIN_KEYSTORE_H
+
+class CKeyStore
+{
+public:
+    std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
+    mutable CCriticalSection cs_mapKeys;
+    virtual bool AddKey(const CKey& key);
+    bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
+    {
+        return (mapKeys.count(vchPubKey) > 0);
+    }
+    bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CPrivKey& keyOut) const
+    {
+        std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
+        if (mi != mapKeys.end())
+        {
+            keyOut = (*mi).second;
+            return true;
+        }
+        return false;
+    }
+    std::vector<unsigned char> GenerateNewKey();
+};
+
+#endif
index 0456041..594f1d3 100644 (file)
@@ -2,7 +2,12 @@
 // 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"
+#include "db.h"
+#include "net.h"
+#include "init.h"
 #include "cryptopp/sha.h"
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 
 using namespace std;
 using namespace boost;
@@ -11,8 +16,14 @@ using namespace boost;
 // Global state
 //
 
+CCriticalSection cs_setpwalletRegistered;
+set<CWallet*> setpwalletRegistered;
+
 CCriticalSection cs_main;
 
+CCriticalSection cs_mapPubKeys;
+map<uint160, vector<unsigned char> > mapPubKeys;
+
 map<uint256, CTransaction> mapTransactions;
 CCriticalSection cs_mapTransactions;
 unsigned int nTransactionsUpdated = 0;
@@ -21,6 +32,8 @@ map<COutPoint, CInPoint> mapNextTx;
 map<uint256, CBlockIndex*> mapBlockIndex;
 uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
 CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
+const int nTotalBlocksEstimate = 134444; // Conservative estimate of total nr of blocks on main chain
+const int nInitialBlockThreshold = 120; // Regard blocks up until N-threshold as "initial download"
 CBlockIndex* pindexGenesisBlock = NULL;
 int nBestHeight = -1;
 CBigNum bnBestChainWork = 0;
@@ -35,22 +48,6 @@ multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
 map<uint256, CDataStream*> mapOrphanTransactions;
 multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
 
-map<uint256, CWalletTx> mapWallet;
-vector<uint256> vWalletUpdated;
-CCriticalSection cs_mapWallet;
-
-map<vector<unsigned char>, CPrivKey> mapKeys;
-map<uint160, vector<unsigned char> > mapPubKeys;
-CCriticalSection cs_mapKeys;
-CKey keyUser;
-
-map<uint256, int> mapRequestCount;
-CCriticalSection cs_mapRequestCount;
-
-map<string, string> mapAddressBook;
-CCriticalSection cs_mapAddressBook;
-
-vector<unsigned char> vchDefaultKey;
 
 double dHashesPerSec;
 int64 nHPSTimerStart;
@@ -77,151 +74,82 @@ int fUseUPnP = false;
 
 //////////////////////////////////////////////////////////////////////////////
 //
-// mapKeys
+// dispatching functions
 //
 
-bool AddKey(const CKey& key)
+void RegisterWallet(CWallet* pwalletIn)
 {
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(cs_setpwalletRegistered)
     {
-        mapKeys[key.GetPubKey()] = key.GetPrivKey();
-        mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
+        setpwalletRegistered.insert(pwalletIn);
     }
-    return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
 }
 
-vector<unsigned char> GenerateNewKey()
+void UnregisterWallet(CWallet* pwalletIn)
 {
-    RandAddSeedPerfmon();
-    CKey key;
-    key.MakeNewKey();
-    if (!AddKey(key))
-        throw runtime_error("GenerateNewKey() : AddKey failed");
-    return key.GetPubKey();
+    CRITICAL_BLOCK(cs_setpwalletRegistered)
+    {
+        setpwalletRegistered.erase(pwalletIn);
+    }
 }
 
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// mapWallet
-//
-
-bool AddToWallet(const CWalletTx& wtxIn)
+bool static IsFromMe(CTransaction& tx)
 {
-    uint256 hash = wtxIn.GetHash();
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        // Inserts only if not already there, returns tx inserted or tx found
-        pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
-        CWalletTx& wtx = (*ret.first).second;
-        bool fInsertedNew = ret.second;
-        if (fInsertedNew)
-            wtx.nTimeReceived = GetAdjustedTime();
-
-        bool fUpdated = false;
-        if (!fInsertedNew)
-        {
-            // Merge
-            if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
-            {
-                wtx.hashBlock = wtxIn.hashBlock;
-                fUpdated = true;
-            }
-            if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
-            {
-                wtx.vMerkleBranch = wtxIn.vMerkleBranch;
-                wtx.nIndex = wtxIn.nIndex;
-                fUpdated = true;
-            }
-            if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
-            {
-                wtx.fFromMe = wtxIn.fFromMe;
-                fUpdated = true;
-            }
-            fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
-        }
-
-        //// debug print
-        printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        if (pwallet->IsFromMe(tx))
+            return true;
+    return false;
+}
 
-        // Write to disk
-        if (fInsertedNew || fUpdated)
-            if (!wtx.WriteToDisk())
-                return false;
+bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        if (pwallet->GetTransaction(hashTx,wtx))
+            return true;
+    return false;
+}
 
-        // If default receiving address gets used, replace it with a new one
-        CScript scriptDefaultKey;
-        scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
-        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-        {
-            if (txout.scriptPubKey == scriptDefaultKey)
-            {
-                CWalletDB walletdb;
-                vchDefaultKey = GetKeyFromKeyPool();
-                walletdb.WriteDefaultKey(vchDefaultKey);
-                walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
-            }
-        }
+void static EraseFromWallets(uint256 hash)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->EraseFromWallet(hash);
+}
 
-        // Notify UI
-        vWalletUpdated.push_back(hash);
-    }
+void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
+}
 
-    // Refresh UI
-    MainFrameRepaint();
-    return true;
+void static SetBestChain(const CBlockLocator& loc)
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->SetBestChain(loc);
 }
 
-bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false)
+void static UpdatedTransaction(const uint256& hashTx)
 {
-    uint256 hash = tx.GetHash();
-    bool fExisted = mapWallet.count(hash);
-    if (fExisted && !fUpdate) return false;
-    if (fExisted || tx.IsMine() || tx.IsFromMe())
-    {
-        CWalletTx wtx(tx);
-        // Get merkle branch if transaction was found in a block
-        if (pblock)
-            wtx.SetMerkleBranch(pblock);
-        return AddToWallet(wtx);
-    }
-    return false;
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->UpdatedTransaction(hashTx);
 }
 
-bool EraseFromWallet(uint256 hash)
+void static PrintWallets(const CBlock& block)
 {
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        if (mapWallet.erase(hash))
-            CWalletDB().EraseTx(hash);
-    }
-    return true;
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->PrintWallet(block);
 }
 
-void WalletUpdateSpent(const COutPoint& prevout)
+void static Inventory(const uint256& hash)
 {
-    // Anytime a signature is successfully verified, it's proof the outpoint is spent.
-    // Update the wallet spent flag if it doesn't know due to wallet.dat being
-    // restored from backup or the user making copies of wallet.dat.
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-        if (mi != mapWallet.end())
-        {
-            CWalletTx& wtx = (*mi).second;
-            if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine())
-            {
-                printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
-                wtx.MarkSpent(prevout.n);
-                wtx.WriteToDisk();
-                vWalletUpdated.push_back(prevout.hash);
-            }
-        }
-    }
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->Inventory(hash);
 }
 
+void static ResendWalletTransactions()
+{
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+        pwallet->ResendWalletTransactions();
+}
 
 
 
@@ -234,7 +162,7 @@ void WalletUpdateSpent(const COutPoint& prevout)
 // mapOrphanTransactions
 //
 
-void AddOrphanTx(const CDataStream& vMsg)
+void static AddOrphanTx(const CDataStream& vMsg)
 {
     CTransaction tx;
     CDataStream(vMsg) >> tx;
@@ -246,7 +174,7 @@ void AddOrphanTx(const CDataStream& vMsg)
         mapOrphanTransactionsByPrev.insert(make_pair(txin.prevout.hash, pvMsg));
 }
 
-void EraseOrphanTx(uint256 hash)
+void static EraseOrphanTx(uint256 hash)
 {
     if (!mapOrphanTransactions.count(hash))
         return;
@@ -308,190 +236,6 @@ bool CTransaction::ReadFromDisk(COutPoint prevout)
     return ReadFromDisk(txdb, prevout, txindex);
 }
 
-bool CTxIn::IsMine() const
-{
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-        if (mi != mapWallet.end())
-        {
-            const CWalletTx& prev = (*mi).second;
-            if (prevout.n < prev.vout.size())
-                if (prev.vout[prevout.n].IsMine())
-                    return true;
-        }
-    }
-    return false;
-}
-
-int64 CTxIn::GetDebit() const
-{
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-        if (mi != mapWallet.end())
-        {
-            const CWalletTx& prev = (*mi).second;
-            if (prevout.n < prev.vout.size())
-                if (prev.vout[prevout.n].IsMine())
-                    return prev.vout[prevout.n].nValue;
-        }
-    }
-    return 0;
-}
-
-int64 CWalletTx::GetTxTime() const
-{
-    if (!fTimeReceivedIsTxTime && hashBlock != 0)
-    {
-        // If we did not receive the transaction directly, we rely on the block's
-        // time to figure out when it happened.  We use the median over a range
-        // of blocks to try to filter out inaccurate block times.
-        map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
-        if (mi != mapBlockIndex.end())
-        {
-            CBlockIndex* pindex = (*mi).second;
-            if (pindex)
-                return pindex->GetMedianTime();
-        }
-    }
-    return nTimeReceived;
-}
-
-int CWalletTx::GetRequestCount() const
-{
-    // Returns -1 if it wasn't being tracked
-    int nRequests = -1;
-    CRITICAL_BLOCK(cs_mapRequestCount)
-    {
-        if (IsCoinBase())
-        {
-            // Generated block
-            if (hashBlock != 0)
-            {
-                map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
-                if (mi != mapRequestCount.end())
-                    nRequests = (*mi).second;
-            }
-        }
-        else
-        {
-            // Did anyone request this transaction?
-            map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
-            if (mi != mapRequestCount.end())
-            {
-                nRequests = (*mi).second;
-
-                // How about the block it's in?
-                if (nRequests == 0 && hashBlock != 0)
-                {
-                    map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
-                    if (mi != mapRequestCount.end())
-                        nRequests = (*mi).second;
-                    else
-                        nRequests = 1; // If it's in someone else's block it must have got out
-                }
-            }
-        }
-    }
-    return nRequests;
-}
-
-void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<string, int64> >& listReceived,
-                           list<pair<string, int64> >& listSent, int64& nFee, string& strSentAccount) const
-{
-    nGeneratedImmature = nGeneratedMature = nFee = 0;
-    listReceived.clear();
-    listSent.clear();
-    strSentAccount = strFromAccount;
-
-    if (IsCoinBase())
-    {
-        if (GetBlocksToMaturity() > 0)
-            nGeneratedImmature = CTransaction::GetCredit();
-        else
-            nGeneratedMature = GetCredit();
-        return;
-    }
-
-    // Compute fee:
-    int64 nDebit = GetDebit();
-    if (nDebit > 0) // debit>0 means we signed/sent this transaction
-    {
-        int64 nValueOut = GetValueOut();
-        nFee = nDebit - nValueOut;
-    }
-
-    // Sent/received.  Standard client will never generate a send-to-multiple-recipients,
-    // but non-standard clients might (so return a list of address/amount pairs)
-    BOOST_FOREACH(const CTxOut& txout, vout)
-    {
-        string address;
-        uint160 hash160;
-        vector<unsigned char> vchPubKey;
-        if (ExtractHash160(txout.scriptPubKey, hash160))
-            address = Hash160ToAddress(hash160);
-        else if (ExtractPubKey(txout.scriptPubKey, false, vchPubKey))
-            address = PubKeyToAddress(vchPubKey);
-        else
-        {
-            printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
-                   this->GetHash().ToString().c_str());
-            address = " unknown ";
-        }
-
-        // Don't report 'change' txouts
-        if (nDebit > 0 && txout.IsChange())
-            continue;
-
-        if (nDebit > 0)
-            listSent.push_back(make_pair(address, txout.nValue));
-
-        if (txout.IsMine())
-            listReceived.push_back(make_pair(address, txout.nValue));
-    }
-
-}
-
-void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived, 
-                                  int64& nSent, int64& nFee) const
-{
-    nGenerated = nReceived = nSent = nFee = 0;
-
-    int64 allGeneratedImmature, allGeneratedMature, allFee;
-    allGeneratedImmature = allGeneratedMature = allFee = 0;
-    string strSentAccount;
-    list<pair<string, int64> > listReceived;
-    list<pair<string, int64> > listSent;
-    GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
-
-    if (strAccount == "")
-        nGenerated = allGeneratedMature;
-    if (strAccount == strSentAccount)
-    {
-        BOOST_FOREACH(const PAIRTYPE(string,int64)& s, listSent)
-            nSent += s.second;
-        nFee = allFee;
-    }
-    CRITICAL_BLOCK(cs_mapAddressBook)
-    {
-        BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
-        {
-            if (mapAddressBook.count(r.first))
-            {
-                if (mapAddressBook[r.first] == strAccount)
-                {
-                    nReceived += r.second;
-                }
-            }
-            else if (strAccount.empty())
-            {
-                nReceived += r.second;
-            }
-        }
-    }
-}
-
 
 
 int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
@@ -547,69 +291,6 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
 
 
 
-void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
-{
-    vtxPrev.clear();
-
-    const int COPY_DEPTH = 3;
-    if (SetMerkleBranch() < COPY_DEPTH)
-    {
-        vector<uint256> vWorkQueue;
-        BOOST_FOREACH(const CTxIn& txin, vin)
-            vWorkQueue.push_back(txin.prevout.hash);
-
-        // This critsect is OK because txdb is already open
-        CRITICAL_BLOCK(cs_mapWallet)
-        {
-            map<uint256, const CMerkleTx*> mapWalletPrev;
-            set<uint256> setAlreadyDone;
-            for (int i = 0; i < vWorkQueue.size(); i++)
-            {
-                uint256 hash = vWorkQueue[i];
-                if (setAlreadyDone.count(hash))
-                    continue;
-                setAlreadyDone.insert(hash);
-
-                CMerkleTx tx;
-                if (mapWallet.count(hash))
-                {
-                    tx = mapWallet[hash];
-                    BOOST_FOREACH(const CMerkleTx& txWalletPrev, mapWallet[hash].vtxPrev)
-                        mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
-                }
-                else if (mapWalletPrev.count(hash))
-                {
-                    tx = *mapWalletPrev[hash];
-                }
-                else if (!fClient && txdb.ReadDiskTx(hash, tx))
-                {
-                    ;
-                }
-                else
-                {
-                    printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
-                    continue;
-                }
-
-                int nDepth = tx.SetMerkleBranch();
-                vtxPrev.push_back(tx);
-
-                if (nDepth < COPY_DEPTH)
-                    BOOST_FOREACH(const CTxIn& txin, tx.vin)
-                        vWorkQueue.push_back(txin.prevout.hash);
-            }
-        }
-    }
-
-    reverse(vtxPrev.begin(), vtxPrev.end());
-}
-
-
-
-
-
-
-
 
 
 
@@ -751,7 +432,7 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
                 nLastTime = nNow;
                 // -limitfreerelay unit is thousand-bytes-per-minute
                 // At default rate it would take over a month to fill 1GB
-                if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe())
+                if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this))
                     return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
                 if (fDebug)
                     printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
@@ -774,12 +455,17 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
     ///// are we sure this is ok when loading transactions or restoring block txes
     // If updated, erase old tx from wallet
     if (ptxOld)
-        EraseFromWallet(ptxOld->GetHash());
+        EraseFromWallets(ptxOld->GetHash());
 
     printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
     return true;
 }
 
+bool CTransaction::AcceptToMemoryPool(bool fCheckInputs, bool* pfMissingInputs)
+{
+    CTxDB txdb("r");
+    return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
+}
 
 bool CTransaction::AddToMemoryPoolUnchecked()
 {
@@ -863,6 +549,12 @@ bool CMerkleTx::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs)
     }
 }
 
+bool CMerkleTx::AcceptToMemoryPool()
+{
+    CTxDB txdb("r");
+    return AcceptToMemoryPool(txdb);
+}
+
 
 
 bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
@@ -884,148 +576,10 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
     return false;
 }
 
-int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
+bool CWalletTx::AcceptWalletTransaction() 
 {
-    int ret = 0;
-
-    CBlockIndex* pindex = pindexStart;
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        while (pindex)
-        {
-            CBlock block;
-            block.ReadFromDisk(pindex, true);
-            BOOST_FOREACH(CTransaction& tx, block.vtx)
-            {
-                if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
-                    ret++;
-            }
-            pindex = pindex->pnext;
-        }
-    }
-    return ret;
-}
-
-void ReacceptWalletTransactions()
-{
-    CTxDB txdb("r");
-    bool fRepeat = true;
-    while (fRepeat) CRITICAL_BLOCK(cs_mapWallet)
-    {
-        fRepeat = false;
-        vector<CDiskTxPos> vMissingTx;
-        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
-        {
-            CWalletTx& wtx = item.second;
-            if (wtx.IsCoinBase() && wtx.IsSpent(0))
-                continue;
-
-            CTxIndex txindex;
-            bool fUpdated = false;
-            if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
-            {
-                // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
-                if (txindex.vSpent.size() != wtx.vout.size())
-                {
-                    printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
-                    continue;
-                }
-                for (int i = 0; i < txindex.vSpent.size(); i++)
-                {
-                    if (wtx.IsSpent(i))
-                        continue;
-                    if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
-                    {
-                        wtx.MarkSpent(i);
-                        fUpdated = true;
-                        vMissingTx.push_back(txindex.vSpent[i]);
-                    }
-                }
-                if (fUpdated)
-                {
-                    printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
-                    wtx.MarkDirty();
-                    wtx.WriteToDisk();
-                }
-            }
-            else
-            {
-                // Reaccept any txes of ours that aren't already in a block
-                if (!wtx.IsCoinBase())
-                    wtx.AcceptWalletTransaction(txdb, false);
-            }
-        }
-        if (!vMissingTx.empty())
-        {
-            // TODO: optimize this to scan just part of the block chain?
-            if (ScanForWalletTransactions(pindexGenesisBlock))
-                fRepeat = true;  // Found missing transactions: re-do Reaccept.
-        }
-    }
-}
-
-
-void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
-{
-    BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
-    {
-        if (!tx.IsCoinBase())
-        {
-            uint256 hash = tx.GetHash();
-            if (!txdb.ContainsTx(hash))
-                RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
-        }
-    }
-    if (!IsCoinBase())
-    {
-        uint256 hash = GetHash();
-        if (!txdb.ContainsTx(hash))
-        {
-            printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
-            RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
-        }
-    }
-}
-
-void ResendWalletTransactions()
-{
-    // Do this infrequently and randomly to avoid giving away
-    // that these are our transactions.
-    static int64 nNextTime;
-    if (GetTime() < nNextTime)
-        return;
-    bool fFirst = (nNextTime == 0);
-    nNextTime = GetTime() + GetRand(30 * 60);
-    if (fFirst)
-        return;
-
-    // Only do it if there's been a new block since last time
-    static int64 nLastTime;
-    if (nTimeBestReceived < nLastTime)
-        return;
-    nLastTime = GetTime();
-
-    // Rebroadcast any of our txes that aren't in a block yet
-    printf("ResendWalletTransactions()\n");
     CTxDB txdb("r");
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        // Sort them in chronological order
-        multimap<unsigned int, CWalletTx*> mapSorted;
-        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
-        {
-            CWalletTx& wtx = item.second;
-            // Don't rebroadcast until it's had plenty of time that
-            // it should have gotten in already by now.
-            if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
-                mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
-        }
-        BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
-        {
-            CWalletTx& wtx = *item.second;
-            wtx.RelayWalletTransaction(txdb);
-        }
-    }
+    return AcceptWalletTransaction(txdb);
 }
 
 int CTxIndex::GetDepthInMainChain() const
@@ -1072,7 +626,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
     return true;
 }
 
-uint256 GetOrphanRoot(const CBlock* pblock)
+uint256 static GetOrphanRoot(const CBlock* pblock)
 {
     // Work back to the first block in the orphan chain
     while (mapOrphanBlocks.count(pblock->hashPrevBlock))
@@ -1080,7 +634,7 @@ uint256 GetOrphanRoot(const CBlock* pblock)
     return pblock->GetHash();
 }
 
-int64 GetBlockValue(int nHeight, int64 nFees)
+int64 static GetBlockValue(int nHeight, int64 nFees)
 {
     int64 nSubsidy = 50 * COIN;
 
@@ -1090,7 +644,7 @@ int64 GetBlockValue(int nHeight, int64 nFees)
     return nSubsidy + nFees;
 }
 
-unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
+unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast)
 {
     const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
     const int64 nTargetSpacing = 10 * 60;
@@ -1152,9 +706,22 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
     return true;
 }
 
+// Return conservative estimate of total number of blocks, 0 if unknown
+int GetTotalBlocksEstimate()
+{
+    if(fTestNet)
+    {
+        return 0;
+    }
+    else
+    {
+        return nTotalBlocksEstimate;
+    }
+}
+
 bool IsInitialBlockDownload()
 {
-    if (pindexBest == NULL || (!fTestNet && nBestHeight < 118000))
+    if (pindexBest == NULL || nBestHeight < (GetTotalBlocksEstimate()-nInitialBlockThreshold))
         return true;
     static int64 nLastUpdate;
     static CBlockIndex* pindexLastBest;
@@ -1167,7 +734,7 @@ bool IsInitialBlockDownload()
             pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
 }
 
-void InvalidChainFound(CBlockIndex* pindexNew)
+void static InvalidChainFound(CBlockIndex* pindexNew)
 {
     if (pindexNew->bnChainWork > bnBestInvalidWork)
     {
@@ -1443,12 +1010,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
 
     // Watch for transactions paying to me
     BOOST_FOREACH(CTransaction& tx, vtx)
-        AddToWalletIfInvolvingMe(tx, this, true);
+        SyncWithWallets(tx, this, true);
 
     return true;
 }
 
-bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
+bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
 {
     printf("REORGANIZE\n");
 
@@ -1586,10 +1153,8 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
     // Update best block in wallet (so we can detect restored wallets)
     if (!IsInitialBlockDownload())
     {
-        CWalletDB walletdb;
         const CBlockLocator locator(pindexNew);
-        if (!walletdb.WriteBestBlock(locator))
-            return error("SetBestChain() : WriteWalletBest failed");
+        ::SetBestChain(locator);
     }
 
     // New best block
@@ -1643,8 +1208,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
     {
         // Notify UI to display prev block's coinbase if it was ours
         static uint256 hashPrevBestCoinBase;
-        CRITICAL_BLOCK(cs_mapWallet)
-            vWalletUpdated.push_back(hashPrevBestCoinBase);
+        UpdatedTransaction(hashPrevBestCoinBase);
         hashPrevBestCoinBase = vtx[0].GetHash();
     }
 
@@ -1730,7 +1294,8 @@ bool CBlock::AcceptBlock()
             (nHeight ==  70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
             (nHeight ==  74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")) ||
             (nHeight == 105000 && hash != uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")) ||
-            (nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553")))
+            (nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553")) ||
+            (nHeight == 134444 && hash != uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")))
             return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
 
     // Write block to history file
@@ -1747,13 +1312,13 @@ bool CBlock::AcceptBlock()
     if (hashBestChain == hash)
         CRITICAL_BLOCK(cs_vNodes)
             BOOST_FOREACH(CNode* pnode, vNodes)
-                if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 118000))
+                if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 134444))
                     pnode->PushInventory(CInv(MSG_BLOCK, hash));
 
     return true;
 }
 
-bool ProcessBlock(CNode* pfrom, CBlock* pblock)
+bool static ProcessBlock(CNode* pfrom, CBlock* pblock)
 {
     // Check for duplicate
     uint256 hash = pblock->GetHash();
@@ -1815,7 +1380,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
 
 
 template<typename Stream>
-bool ScanMessageStart(Stream& s)
+bool static ScanMessageStart(Stream& s)
 {
     // Scan ahead to the next pchMessageStart, which should normally be immediately
     // at the file pointer.  Leaves file pointer at end of pchMessageStart.
@@ -2030,7 +1595,7 @@ void PrintBlockTree()
             for (int i = 0; i < nCol; i++)
                 printf("| ");
             printf("|\n");
-        }
+       }
         nPrevCol = nCol;
 
         // print columns
@@ -2048,16 +1613,7 @@ void PrintBlockTree()
             DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
             block.vtx.size());
 
-        CRITICAL_BLOCK(cs_mapWallet)
-        {
-            if (mapWallet.count(block.vtx[0].GetHash()))
-            {
-                CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
-                printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
-            }
-        }
-        printf("\n");
-
+        PrintWallets(block);
 
         // put the main timechain first
         vector<CBlockIndex*>& vNext = mapNext[pindex];
@@ -2197,7 +1753,7 @@ bool CAlert::ProcessAlert()
 //
 
 
-bool AlreadyHave(CTxDB& txdb, const CInv& inv)
+bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
 {
     switch (inv.type)
     {
@@ -2217,128 +1773,7 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
 char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
 
 
-bool ProcessMessages(CNode* pfrom)
-{
-    CDataStream& vRecv = pfrom->vRecv;
-    if (vRecv.empty())
-        return true;
-    //if (fDebug)
-    //    printf("ProcessMessages(%u bytes)\n", vRecv.size());
-
-    //
-    // Message format
-    //  (4) message start
-    //  (12) command
-    //  (4) size
-    //  (4) checksum
-    //  (x) data
-    //
-
-    loop
-    {
-        // Scan for message start
-        CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
-        int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
-        if (vRecv.end() - pstart < nHeaderSize)
-        {
-            if (vRecv.size() > nHeaderSize)
-            {
-                printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
-                vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
-            }
-            break;
-        }
-        if (pstart - vRecv.begin() > 0)
-            printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());
-        vRecv.erase(vRecv.begin(), pstart);
-
-        // Read header
-        vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
-        CMessageHeader hdr;
-        vRecv >> hdr;
-        if (!hdr.IsValid())
-        {
-            printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
-            continue;
-        }
-        string strCommand = hdr.GetCommand();
-
-        // Message size
-        unsigned int nMessageSize = hdr.nMessageSize;
-        if (nMessageSize > MAX_SIZE)
-        {
-            printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
-            continue;
-        }
-        if (nMessageSize > vRecv.size())
-        {
-            // Rewind and wait for rest of message
-            vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
-            break;
-        }
-
-        // Checksum
-        if (vRecv.GetVersion() >= 209)
-        {
-            uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
-            unsigned int nChecksum = 0;
-            memcpy(&nChecksum, &hash, sizeof(nChecksum));
-            if (nChecksum != hdr.nChecksum)
-            {
-                printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
-                       strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
-                continue;
-            }
-        }
-
-        // Copy message to its own buffer
-        CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
-        vRecv.ignore(nMessageSize);
-
-        // Process message
-        bool fRet = false;
-        try
-        {
-            CRITICAL_BLOCK(cs_main)
-                fRet = ProcessMessage(pfrom, strCommand, vMsg);
-            if (fShutdown)
-                return true;
-        }
-        catch (std::ios_base::failure& e)
-        {
-            if (strstr(e.what(), "end of data"))
-            {
-                // Allow exceptions from underlength message on vRecv
-                printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
-            }
-            else if (strstr(e.what(), "size too large"))
-            {
-                // Allow exceptions from overlong size
-                printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
-            }
-            else
-            {
-                PrintExceptionContinue(&e, "ProcessMessage()");
-            }
-        }
-        catch (std::exception& e) {
-            PrintExceptionContinue(&e, "ProcessMessage()");
-        } catch (...) {
-            PrintExceptionContinue(NULL, "ProcessMessage()");
-        }
-
-        if (!fRet)
-            printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
-    }
-
-    vRecv.Compact();
-    return true;
-}
-
-
-
-
-bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
+bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 {
     static map<unsigned int, vector<unsigned char> > mapReuseKey;
     RandAddSeedPerfmon();
@@ -2535,12 +1970,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                 pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
 
             // Track requests for our stuff
-            CRITICAL_BLOCK(cs_mapRequestCount)
-            {
-                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
-                if (mi != mapRequestCount.end())
-                    (*mi).second++;
-            }
+            Inventory(inv.hash);
         }
     }
 
@@ -2593,12 +2023,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             }
 
             // Track requests for our stuff
-            CRITICAL_BLOCK(cs_mapRequestCount)
-            {
-                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
-                if (mi != mapRequestCount.end())
-                    (*mi).second++;
-            }
+            Inventory(inv.hash);
         }
     }
 
@@ -2616,20 +2041,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         if (pindex)
             pindex = pindex->pnext;
         int nLimit = 500 + locator.GetDistanceBack();
+        unsigned int nBytes = 0;
         printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
         for (; pindex; pindex = pindex->pnext)
         {
             if (pindex->GetBlockHash() == hashStop)
             {
-                printf("  getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
+                printf("  getblocks stopping at %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes);
                 break;
             }
             pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
-            if (--nLimit <= 0)
+            CBlock block;
+            block.ReadFromDisk(pindex, true);
+            nBytes += block.GetSerializeSize(SER_NETWORK);
+            if (--nLimit <= 0 || nBytes >= SendBufferSize()/2)
             {
                 // When this block is requested, we'll send an inv that'll make them
                 // getblocks the next batch of inventory.
-                printf("  getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
+                printf("  getblocks stopping at limit %d %s (%u bytes)\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str(), nBytes);
                 pfrom->hashContinue = pindex->GetBlockHash();
                 break;
             }
@@ -2686,7 +2115,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         bool fMissingInputs = false;
         if (tx.AcceptToMemoryPool(true, &fMissingInputs))
         {
-            AddToWalletIfInvolvingMe(tx, NULL, true);
+            SyncWithWallets(tx, NULL, true);
             RelayMessage(inv, vMsg);
             mapAlreadyAskedFor.erase(inv);
             vWorkQueue.push_back(inv.hash);
@@ -2707,7 +2136,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                     if (tx.AcceptToMemoryPool(true))
                     {
                         printf("   accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
-                        AddToWalletIfInvolvingMe(tx, NULL, true);
+                        SyncWithWallets(tx, NULL, true);
                         RelayMessage(inv, vMsg);
                         mapAlreadyAskedFor.erase(inv);
                         vWorkQueue.push_back(inv.hash);
@@ -2784,7 +2213,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 
         // Keep giving the same key to the same ip until they use it
         if (!mapReuseKey.count(pfrom->addr.ip))
-            mapReuseKey[pfrom->addr.ip] = GetKeyFromKeyPool();
+            mapReuseKey[pfrom->addr.ip] = pwalletMain->GetKeyFromKeyPool();
 
         // Send back approval of order and pubkey to use
         CScript scriptPubKey;
@@ -2793,37 +2222,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     }
 
 
-    else if (strCommand == "submitorder")
-    {
-        uint256 hashReply;
-        vRecv >> hashReply;
-
-        if (!GetBoolArg("-allowreceivebyip"))
-        {
-            pfrom->PushMessage("reply", hashReply, (int)2);
-            return true;
-        }
-
-        CWalletTx wtxNew;
-        vRecv >> wtxNew;
-        wtxNew.fFromMe = false;
-
-        // Broadcast
-        if (!wtxNew.AcceptWalletTransaction())
-        {
-            pfrom->PushMessage("reply", hashReply, (int)1);
-            return error("submitorder AcceptWalletTransaction() failed, returning error 1");
-        }
-        wtxNew.fTimeReceivedIsTxTime = true;
-        AddToWallet(wtxNew);
-        wtxNew.RelayWalletTransaction();
-        mapReuseKey.erase(pfrom->addr.ip);
-
-        // Send back confirmation
-        pfrom->PushMessage("reply", hashReply, (int)0);
-    }
-
-
     else if (strCommand == "reply")
     {
         uint256 hashReply;
@@ -2880,12 +2278,123 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     return true;
 }
 
+bool ProcessMessages(CNode* pfrom)
+{
+    CDataStream& vRecv = pfrom->vRecv;
+    if (vRecv.empty())
+        return true;
+    //if (fDebug)
+    //    printf("ProcessMessages(%u bytes)\n", vRecv.size());
 
+    //
+    // Message format
+    //  (4) message start
+    //  (12) command
+    //  (4) size
+    //  (4) checksum
+    //  (x) data
+    //
 
+    loop
+    {
+        // Scan for message start
+        CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
+        int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
+        if (vRecv.end() - pstart < nHeaderSize)
+        {
+            if (vRecv.size() > nHeaderSize)
+            {
+                printf("\n\nPROCESSMESSAGE MESSAGESTART NOT FOUND\n\n");
+                vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
+            }
+            break;
+        }
+        if (pstart - vRecv.begin() > 0)
+            printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin());
+        vRecv.erase(vRecv.begin(), pstart);
 
+        // Read header
+        vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
+        CMessageHeader hdr;
+        vRecv >> hdr;
+        if (!hdr.IsValid())
+        {
+            printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str());
+            continue;
+        }
+        string strCommand = hdr.GetCommand();
 
+        // Message size
+        unsigned int nMessageSize = hdr.nMessageSize;
+        if (nMessageSize > MAX_SIZE)
+        {
+            printf("ProcessMessage(%s, %u bytes) : nMessageSize > MAX_SIZE\n", strCommand.c_str(), nMessageSize);
+            continue;
+        }
+        if (nMessageSize > vRecv.size())
+        {
+            // Rewind and wait for rest of message
+            vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
+            break;
+        }
 
+        // Checksum
+        if (vRecv.GetVersion() >= 209)
+        {
+            uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
+            unsigned int nChecksum = 0;
+            memcpy(&nChecksum, &hash, sizeof(nChecksum));
+            if (nChecksum != hdr.nChecksum)
+            {
+                printf("ProcessMessage(%s, %u bytes) : CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
+                       strCommand.c_str(), nMessageSize, nChecksum, hdr.nChecksum);
+                continue;
+            }
+        }
 
+        // Copy message to its own buffer
+        CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
+        vRecv.ignore(nMessageSize);
+
+        // Process message
+        bool fRet = false;
+        try
+        {
+            CRITICAL_BLOCK(cs_main)
+                fRet = ProcessMessage(pfrom, strCommand, vMsg);
+            if (fShutdown)
+                return true;
+        }
+        catch (std::ios_base::failure& e)
+        {
+            if (strstr(e.what(), "end of data"))
+            {
+                // Allow exceptions from underlength message on vRecv
+                printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
+            }
+            else if (strstr(e.what(), "size too large"))
+            {
+                // Allow exceptions from overlong size
+                printf("ProcessMessage(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
+            }
+            else
+            {
+                PrintExceptionContinue(&e, "ProcessMessage()");
+            }
+        }
+        catch (std::exception& e) {
+            PrintExceptionContinue(&e, "ProcessMessage()");
+        } catch (...) {
+            PrintExceptionContinue(NULL, "ProcessMessage()");
+        }
+
+        if (!fRet)
+            printf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand.c_str(), nMessageSize);
+    }
+
+    vRecv.Compact();
+    return true;
+}
 
 
 bool SendMessages(CNode* pto, bool fSendTrickle)
@@ -3010,16 +2519,10 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
                     // always trickle our own transactions
                     if (!fTrickleWait)
                     {
-                        TRY_CRITICAL_BLOCK(cs_mapWallet)
-                        {
-                            map<uint256, CWalletTx>::iterator mi = mapWallet.find(inv.hash);
-                            if (mi != mapWallet.end())
-                            {
-                                CWalletTx& wtx = (*mi).second;
-                                if (wtx.fFromMe)
-                                    fTrickleWait = true;
-                            }
-                        }
+                        CWalletTx wtx;
+                        if (GetTransaction(inv.hash, wtx))
+                            if (wtx.fFromMe)
+                                fTrickleWait = true;
                     }
 
                     if (fTrickleWait)
@@ -3092,57 +2595,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
 // BitcoinMiner
 //
 
-void GenerateBitcoins(bool fGenerate)
-{
-    if (fGenerateBitcoins != fGenerate)
-    {
-        fGenerateBitcoins = fGenerate;
-        CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
-        MainFrameRepaint();
-    }
-    if (fGenerateBitcoins)
-    {
-        int nProcessors = boost::thread::hardware_concurrency();
-        printf("%d processors\n", nProcessors);
-        if (nProcessors < 1)
-            nProcessors = 1;
-        if (fLimitProcessors && nProcessors > nLimitProcessors)
-            nProcessors = nLimitProcessors;
-        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);
-        }
-    }
-}
-
-void ThreadBitcoinMiner(void* parg)
-{
-    try
-    {
-        vnThreadsRunning[3]++;
-        BitcoinMiner();
-        vnThreadsRunning[3]--;
-    }
-    catch (std::exception& e) {
-        vnThreadsRunning[3]--;
-        PrintException(&e, "ThreadBitcoinMiner()");
-    } catch (...) {
-        vnThreadsRunning[3]--;
-        PrintException(NULL, "ThreadBitcoinMiner()");
-    }
-    UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
-    nHPSTimerStart = 0;
-    if (vnThreadsRunning[3] == 0)
-        dHashesPerSec = 0;
-    printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
-}
-
-
-int FormatHashBlocks(void* pbuffer, unsigned int len)
+int static FormatHashBlocks(void* pbuffer, unsigned int len)
 {
     unsigned char* pdata = (unsigned char*)pbuffer;
     unsigned int blocks = 1 + ((len + 8) / 64);
@@ -3175,7 +2628,7 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)
 // between calls, but periodically or if nNonce is 0xffff0000 or above,
 // the block is rebuilt and nNonce starts over at zero.
 //
-unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
+unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
 {
     unsigned int& nNonce = *(unsigned int*)(pdata + 12);
     for (;;)
@@ -3432,7 +2885,7 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
 }
 
 
-bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
+bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
 {
     uint256 hash = pblock->GetHash();
     uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
@@ -3457,8 +2910,8 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
         reservekey.KeepKey();
 
         // Track how many getdata requests this block gets
-        CRITICAL_BLOCK(cs_mapRequestCount)
-            mapRequestCount[pblock->GetHash()] = 0;
+        CRITICAL_BLOCK(wallet.cs_mapRequestCount)
+            wallet.mapRequestCount[pblock->GetHash()] = 0;
 
         // Process this block the same as if we had received it from another node
         if (!ProcessBlock(NULL, pblock))
@@ -3469,14 +2922,15 @@ bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
     return true;
 }
 
+void static ThreadBitcoinMiner(void* parg);
 
-void BitcoinMiner()
+void static BitcoinMiner(CWallet *pwallet)
 {
     printf("BitcoinMiner started\n");
     SetThreadPriority(THREAD_PRIORITY_LOWEST);
 
     // Each thread has its own key and counter
-    CReserveKey reservekey;
+    CReserveKey reservekey(pwallet);
     unsigned int nExtraNonce = 0;
     int64 nPrevTime = 0;
 
@@ -3552,7 +3006,7 @@ void BitcoinMiner()
                     assert(hash == pblock->GetHash());
 
                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
-                    CheckWork(pblock.get(), reservekey);
+                    CheckWork(pblock.get(), *pwalletMain, reservekey);
                     SetThreadPriority(THREAD_PRIORITY_LOWEST);
                     break;
                 }
@@ -3613,421 +3067,53 @@ void BitcoinMiner()
     }
 }
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Actions
-//
-
-
-int64 GetBalance()
-{
-    int64 nStart = GetTimeMillis();
-
-    int64 nTotal = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
-        {
-            CWalletTx* pcoin = &(*it).second;
-            if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
-                continue;
-            nTotal += pcoin->GetAvailableCredit();
-        }
-    }
-
-    //printf("GetBalance() %"PRI64d"ms\n", GetTimeMillis() - nStart);
-    return nTotal;
-}
-
-
-bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
+void static ThreadBitcoinMiner(void* parg)
 {
-    setCoinsRet.clear();
-    nValueRet = 0;
-
-    // List of values less than target
-    pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger;
-    coinLowestLarger.first = INT64_MAX;
-    coinLowestLarger.second.first = NULL;
-    vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue;
-    int64 nTotalLower = 0;
-
-    CRITICAL_BLOCK(cs_mapWallet)
-    {
-       vector<CWalletTx*> vCoins;
-       vCoins.reserve(mapWallet.size());
-       for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
-           vCoins.push_back(&(*it).second);
-       random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
-
-       BOOST_FOREACH(CWalletTx* pcoin, vCoins)
-       {
-            if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
-                continue;
-
-            if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
-                continue;
-
-            int nDepth = pcoin->GetDepthInMainChain();
-            if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
-                continue;
-
-            for (int i = 0; i < pcoin->vout.size(); i++)
-            {
-                if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine())
-                    continue;
-
-                int64 n = pcoin->vout[i].nValue;
-
-                if (n <= 0)
-                    continue;
-
-                pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
-
-                if (n == nTargetValue)
-                {
-                    setCoinsRet.insert(coin.second);
-                    nValueRet += coin.first;
-                    return true;
-                }
-                else if (n < nTargetValue + CENT)
-                {
-                    vValue.push_back(coin);
-                    nTotalLower += n;
-                }
-                else if (n < coinLowestLarger.first)
-                {
-                    coinLowestLarger = coin;
-                }
-            }
-        }
-    }
-
-    if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
-    {
-        for (int i = 0; i < vValue.size(); ++i)
-        {
-            setCoinsRet.insert(vValue[i].second);
-            nValueRet += vValue[i].first;
-        }
-        return true;
-    }
-
-    if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
-    {
-        if (coinLowestLarger.second.first == NULL)
-            return false;
-        setCoinsRet.insert(coinLowestLarger.second);
-        nValueRet += coinLowestLarger.first;
-        return true;
-    }
-
-    if (nTotalLower >= nTargetValue + CENT)
-        nTargetValue += CENT;
-
-    // Solve subset sum by stochastic approximation
-    sort(vValue.rbegin(), vValue.rend());
-    vector<char> vfIncluded;
-    vector<char> vfBest(vValue.size(), true);
-    int64 nBest = nTotalLower;
-
-    for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
-    {
-        vfIncluded.assign(vValue.size(), false);
-        int64 nTotal = 0;
-        bool fReachedTarget = false;
-        for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
-        {
-            for (int i = 0; i < vValue.size(); i++)
-            {
-                if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
-                {
-                    nTotal += vValue[i].first;
-                    vfIncluded[i] = true;
-                    if (nTotal >= nTargetValue)
-                    {
-                        fReachedTarget = true;
-                        if (nTotal < nBest)
-                        {
-                            nBest = nTotal;
-                            vfBest = vfIncluded;
-                        }
-                        nTotal -= vValue[i].first;
-                        vfIncluded[i] = false;
-                    }
-                }
-            }
-        }
-    }
-
-    // If the next larger is still closer, return it
-    if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
+    CWallet* pwallet = (CWallet*)parg;
+    try
     {
-        setCoinsRet.insert(coinLowestLarger.second);
-        nValueRet += coinLowestLarger.first;
+        vnThreadsRunning[3]++;
+        BitcoinMiner(pwallet);
+        vnThreadsRunning[3]--;
     }
-    else {
-        for (int i = 0; i < vValue.size(); i++)
-            if (vfBest[i])
-            {
-                setCoinsRet.insert(vValue[i].second);
-                nValueRet += vValue[i].first;
-            }
-
-        //// debug print
-        printf("SelectCoins() best subset: ");
-        for (int i = 0; i < vValue.size(); i++)
-            if (vfBest[i])
-                printf("%s ", FormatMoney(vValue[i].first).c_str());
-        printf("total %s\n", FormatMoney(nBest).c_str());
+    catch (std::exception& e) {
+        vnThreadsRunning[3]--;
+        PrintException(&e, "ThreadBitcoinMiner()");
+    } catch (...) {
+        vnThreadsRunning[3]--;
+        PrintException(NULL, "ThreadBitcoinMiner()");
     }
-
-    return true;
-}
-
-bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet)
-{
-    return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
-            SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
-            SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
+    UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
+    nHPSTimerStart = 0;
+    if (vnThreadsRunning[3] == 0)
+        dHashesPerSec = 0;
+    printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
 }
 
 
-
-
-bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
 {
-    int64 nValue = 0;
-    BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
-    {
-        if (nValue < 0)
-            return false;
-        nValue += s.second;
-    }
-    if (vecSend.empty() || nValue < 0)
-        return false;
-
-    CRITICAL_BLOCK(cs_main)
+    if (fGenerateBitcoins != fGenerate)
     {
-        // txdb must be opened before the mapWallet lock
-        CTxDB txdb("r");
-        CRITICAL_BLOCK(cs_mapWallet)
-        {
-            nFeeRet = nTransactionFee;
-            loop
-            {
-                wtxNew.vin.clear();
-                wtxNew.vout.clear();
-                wtxNew.fFromMe = true;
-
-                int64 nTotalValue = nValue + nFeeRet;
-                double dPriority = 0;
-                // vouts to the payees
-                BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
-                    wtxNew.vout.push_back(CTxOut(s.second, s.first));
-
-                // Choose coins to use
-                set<pair<CWalletTx*,unsigned int> > setCoins;
-                int64 nValueIn = 0;
-                if (!SelectCoins(nTotalValue, setCoins, nValueIn))
-                    return false;
-                BOOST_FOREACH(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins)
-                {
-                    int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
-                    dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
-                }
-
-                int64 nChange = nValueIn - nValue - nFeeRet;
-
-                // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
-                // or until nChange becomes zero
-                if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
-                {
-                    int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
-                    nChange -= nMoveToFee;
-                    nFeeRet += nMoveToFee;
-                }
-
-                if (nChange > 0)
-                {
-                    // Note: We use a new key here to keep it from being obvious which side is the change.
-                    //  The drawback is that by not reusing a previous key, the change may be lost if a
-                    //  backup is restored, if the backup doesn't have the new private key for the change.
-                    //  If we reused the old key, it would be possible to add code to look for and
-                    //  rediscover unknown transactions that were written with keys of ours to recover
-                    //  post-backup change.
-
-                    // Reserve a new key pair from key pool
-                    vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
-                    assert(mapKeys.count(vchPubKey));
-
-                    // Fill a vout to ourself, using same address type as the payment
-                    CScript scriptChange;
-                    if (vecSend[0].first.GetBitcoinAddressHash160() != 0)
-                        scriptChange.SetBitcoinAddress(vchPubKey);
-                    else
-                        scriptChange << vchPubKey << OP_CHECKSIG;
-
-                    // Insert change txn at random position:
-                    vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
-                    wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
-                }
-                else
-                    reservekey.ReturnKey();
-
-                // Fill vin
-                BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
-                    wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
-
-                // Sign
-                int nIn = 0;
-                BOOST_FOREACH(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins)
-                    if (!SignSignature(*coin.first, wtxNew, nIn++))
-                        return false;
-
-                // Limit size
-                unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
-                if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
-                    return false;
-                dPriority /= nBytes;
-
-                // Check that enough fee is included
-                int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
-                bool fAllowFree = CTransaction::AllowFree(dPriority);
-                int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
-                if (nFeeRet < max(nPayFee, nMinFee))
-                {
-                    nFeeRet = max(nPayFee, nMinFee);
-                    continue;
-                }
-
-                // Fill vtxPrev by copying from previous transactions vtxPrev
-                wtxNew.AddSupportingTransactions(txdb);
-                wtxNew.fTimeReceivedIsTxTime = true;
-
-                break;
-            }
-        }
+        fGenerateBitcoins = fGenerate;
+        WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
+        MainFrameRepaint();
     }
-    return true;
-}
-
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
-{
-    vector< pair<CScript, int64> > vecSend;
-    vecSend.push_back(make_pair(scriptPubKey, nValue));
-    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
-}
-
-// Call after CreateTransaction unless you want to abort
-bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
-{
-    CRITICAL_BLOCK(cs_main)
+    if (fGenerateBitcoins)
     {
-        printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
-        CRITICAL_BLOCK(cs_mapWallet)
-        {
-            // This is only to keep the database open to defeat the auto-flush for the
-            // duration of this scope.  This is the only place where this optimization
-            // maybe makes sense; please don't do it anywhere else.
-            CWalletDB walletdb("r");
-
-            // Take key pair from key pool so it won't be used again
-            reservekey.KeepKey();
-
-            // Add tx to wallet, because if it has change it's also ours,
-            // otherwise just for transaction history.
-            AddToWallet(wtxNew);
-
-            // Mark old coins as spent
-            set<CWalletTx*> setCoins;
-            BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
-            {
-                CWalletTx &pcoin = mapWallet[txin.prevout.hash];
-                pcoin.MarkSpent(txin.prevout.n);
-                pcoin.WriteToDisk();
-                vWalletUpdated.push_back(pcoin.GetHash());
-            }
-        }
-
-        // Track how many getdata requests our transaction gets
-        CRITICAL_BLOCK(cs_mapRequestCount)
-            mapRequestCount[wtxNew.GetHash()] = 0;
-
-        // Broadcast
-        if (!wtxNew.AcceptToMemoryPool())
+        int nProcessors = boost::thread::hardware_concurrency();
+        printf("%d processors\n", nProcessors);
+        if (nProcessors < 1)
+            nProcessors = 1;
+        if (fLimitProcessors && nProcessors > nLimitProcessors)
+            nProcessors = nLimitProcessors;
+        int nAddThreads = nProcessors - vnThreadsRunning[3];
+        printf("Starting %d BitcoinMiner threads\n", nAddThreads);
+        for (int i = 0; i < nAddThreads; i++)
         {
-            // This must not fail. The transaction has already been signed and recorded.
-            printf("CommitTransaction() : Error: Transaction not valid");
-            return false;
+            if (!CreateThread(ThreadBitcoinMiner, pwallet))
+                printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
+            Sleep(10);
         }
-        wtxNew.RelayWalletTransaction();
-    }
-    MainFrameRepaint();
-    return true;
-}
-
-
-
-
-// requires cs_main lock
-string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
-{
-    CReserveKey reservekey;
-    int64 nFeeRequired;
-    if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
-    {
-        string strError;
-        if (nValue + nFeeRequired > GetBalance())
-            strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds  "), FormatMoney(nFeeRequired).c_str());
-        else
-            strError = _("Error: Transaction creation failed  ");
-        printf("SendMoney() : %s", strError.c_str());
-        return strError;
     }
-
-    if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
-        return "ABORTED";
-
-    if (!CommitTransaction(wtxNew, reservekey))
-        return _("Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
-
-    MainFrameRepaint();
-    return "";
-}
-
-
-
-// requires cs_main lock
-string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
-{
-    // Check amount
-    if (nValue <= 0)
-        return _("Invalid amount");
-    if (nValue + nTransactionFee > GetBalance())
-        return _("Insufficient funds");
-
-    // Parse bitcoin address
-    CScript scriptPubKey;
-    if (!scriptPubKey.SetBitcoinAddress(strAddress))
-        return _("Invalid bitcoin address");
-
-    return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
 }
index 8087df3..aa74ac5 100644 (file)
@@ -7,22 +7,25 @@
 #include "bignum.h"
 #include "net.h"
 #include "key.h"
-#include "db.h"
 #include "script.h"
+#include "db.h"
 
 #include <list>
 
-class COutPoint;
-class CInPoint;
-class CDiskTxPos;
-class CCoinBase;
-class CTxIn;
-class CTxOut;
-class CTransaction;
 class CBlock;
 class CBlockIndex;
 class CWalletTx;
+class CWallet;
 class CKeyItem;
+class CReserveKey;
+class CWalletDB;
+
+class CMessageHeader;
+class CAddress;
+class CInv;
+class CRequestTracker;
+class CNode;
+class CBlockIndex;
 
 static const unsigned int MAX_BLOCK_SIZE = 1000000;
 static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
@@ -56,13 +59,11 @@ extern CBigNum bnBestInvalidWork;
 extern uint256 hashBestChain;
 extern CBlockIndex* pindexBest;
 extern unsigned int nTransactionsUpdated;
-extern std::map<uint256, int> mapRequestCount;
-extern CCriticalSection cs_mapRequestCount;
-extern std::map<std::string, std::string> mapAddressBook;
-extern CCriticalSection cs_mapAddressBook;
-extern std::vector<unsigned char> vchDefaultKey;
 extern double dHashesPerSec;
 extern int64 nHPSTimerStart;
+extern int64 nTimeBestReceived;
+extern CCriticalSection cs_setpwalletRegistered;
+extern std::set<CWallet*> setpwalletRegistered;
 
 // Settings
 extern int fGenerateBitcoins;
@@ -78,37 +79,26 @@ extern int fUseUPnP;
 
 
 
+class CReserveKey;
+class CTxDB;
+class CTxIndex;
 
-
+void RegisterWallet(CWallet* pwalletIn);
+void UnregisterWallet(CWallet* pwalletIn);
 bool CheckDiskSpace(uint64 nAdditionalBytes=0);
 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
 FILE* AppendBlockFile(unsigned int& nFileRet);
-bool AddKey(const CKey& key);
-std::vector<unsigned char> GenerateNewKey();
-bool AddToWallet(const CWalletTx& wtxIn);
-void WalletUpdateSpent(const COutPoint& prevout);
-int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
-void ReacceptWalletTransactions();
 bool LoadBlockIndex(bool fAllowNew=true);
 void PrintBlockTree();
 bool ProcessMessages(CNode* pfrom);
-bool ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv);
 bool SendMessages(CNode* pto, bool fSendTrickle);
-int64 GetBalance();
-bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
-bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
-bool BroadcastTransaction(CWalletTx& wtxNew);
-std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
-std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
-void GenerateBitcoins(bool fGenerate);
-void ThreadBitcoinMiner(void* parg);
+void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
 CBlock* CreateNewBlock(CReserveKey& reservekey);
 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
-bool CheckWork(CBlock* pblock, CReserveKey& reservekey);
-void BitcoinMiner();
+bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
 bool CheckProofOfWork(uint256 hash, unsigned int nBits);
+int GetTotalBlocksEstimate();
 bool IsInitialBlockDownload();
 std::string GetWarnings(std::string strFor);
 
@@ -123,6 +113,23 @@ std::string GetWarnings(std::string strFor);
 
 
 
+bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
+
+template<typename T>
+bool WriteSetting(const std::string& strKey, const T& value)
+{
+    bool fOk = false;
+    BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
+    {
+        std::string strWalletFile;
+        if (!GetWalletFile(pwallet, strWalletFile))
+            continue;
+        fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
+    }
+    return fOk;
+}
+
+
 class CDiskTxPos
 {
 public:
@@ -305,9 +312,6 @@ public:
     {
         printf("%s\n", ToString().c_str());
     }
-
-    bool IsMine() const;
-    int64 GetDebit() const;
 };
 
 
@@ -356,36 +360,6 @@ public:
         return SerializeHash(*this);
     }
 
-    bool IsMine() const
-    {
-        return ::IsMine(scriptPubKey);
-    }
-
-    int64 GetCredit() const
-    {
-        if (!MoneyRange(nValue))
-            throw std::runtime_error("CTxOut::GetCredit() : value out of range");
-        return (IsMine() ? nValue : 0);
-    }
-
-    bool IsChange() const
-    {
-        // On a debit transaction, a txout that's mine but isn't in the address book is change
-        std::vector<unsigned char> vchPubKey;
-        if (ExtractPubKey(scriptPubKey, true, vchPubKey))
-            CRITICAL_BLOCK(cs_mapAddressBook)
-                if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
-                    return true;
-        return false;
-    }
-
-    int64 GetChange() const
-    {
-        if (!MoneyRange(nValue))
-            throw std::runtime_error("CTxOut::GetChange() : value out of range");
-        return (IsChange() ? nValue : 0);
-    }
-
     friend bool operator==(const CTxOut& a, const CTxOut& b)
     {
         return (a.nValue       == b.nValue &&
@@ -530,57 +504,6 @@ public:
         return true;
     }
 
-    bool IsMine() const
-    {
-        BOOST_FOREACH(const CTxOut& txout, vout)
-            if (txout.IsMine())
-                return true;
-        return false;
-    }
-
-    bool IsFromMe() const
-    {
-        return (GetDebit() > 0);
-    }
-
-    int64 GetDebit() const
-    {
-        int64 nDebit = 0;
-        BOOST_FOREACH(const CTxIn& txin, vin)
-        {
-            nDebit += txin.GetDebit();
-            if (!MoneyRange(nDebit))
-                throw std::runtime_error("CTransaction::GetDebit() : value out of range");
-        }
-        return nDebit;
-    }
-
-    int64 GetCredit() const
-    {
-        int64 nCredit = 0;
-        BOOST_FOREACH(const CTxOut& txout, vout)
-        {
-            nCredit += txout.GetCredit();
-            if (!MoneyRange(nCredit))
-                throw std::runtime_error("CTransaction::GetCredit() : value out of range");
-        }
-        return nCredit;
-    }
-
-    int64 GetChange() const
-    {
-        if (IsCoinBase())
-            return 0;
-        int64 nChange = 0;
-        BOOST_FOREACH(const CTxOut& txout, vout)
-        {
-            nChange += txout.GetChange();
-            if (!MoneyRange(nChange))
-                throw std::runtime_error("CTransaction::GetChange() : value out of range");
-        }
-        return nChange;
-    }
-
     int64 GetValueOut() const
     {
         int64 nValueOut = 0;
@@ -712,11 +635,7 @@ public:
     bool ClientConnectInputs();
     bool CheckTransaction() const;
     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
-    bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
-    {
-        CTxDB txdb("r");
-        return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
-    }
+    bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
 protected:
     bool AddToMemoryPoolUnchecked();
 public:
@@ -775,307 +694,7 @@ public:
     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
     int GetBlocksToMaturity() const;
     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
-    bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); }
-};
-
-
-
-
-//
-// A transaction with a bunch of additional info that only the owner cares
-// about.  It includes any unrecorded transactions needed to link it back
-// to the block chain.
-//
-class CWalletTx : public CMerkleTx
-{
-public:
-    std::vector<CMerkleTx> vtxPrev;
-    std::map<std::string, std::string> mapValue;
-    std::vector<std::pair<std::string, std::string> > vOrderForm;
-    unsigned int fTimeReceivedIsTxTime;
-    unsigned int nTimeReceived;  // time received by this node
-    char fFromMe;
-    std::string strFromAccount;
-    std::vector<char> vfSpent;
-
-    // memory only
-    mutable char fDebitCached;
-    mutable char fCreditCached;
-    mutable char fAvailableCreditCached;
-    mutable char fChangeCached;
-    mutable int64 nDebitCached;
-    mutable int64 nCreditCached;
-    mutable int64 nAvailableCreditCached;
-    mutable int64 nChangeCached;
-
-    // memory only UI hints
-    mutable unsigned int nTimeDisplayed;
-    mutable int nLinesDisplayed;
-    mutable char fConfirmedDisplayed;
-
-
-    CWalletTx()
-    {
-        Init();
-    }
-
-    CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
-    {
-        Init();
-    }
-
-    CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
-    {
-        Init();
-    }
-
-    void Init()
-    {
-        vtxPrev.clear();
-        mapValue.clear();
-        vOrderForm.clear();
-        fTimeReceivedIsTxTime = false;
-        nTimeReceived = 0;
-        fFromMe = false;
-        strFromAccount.clear();
-        vfSpent.clear();
-        fDebitCached = false;
-        fCreditCached = false;
-        fAvailableCreditCached = false;
-        fChangeCached = false;
-        nDebitCached = 0;
-        nCreditCached = 0;
-        nAvailableCreditCached = 0;
-        nChangeCached = 0;
-        nTimeDisplayed = 0;
-        nLinesDisplayed = 0;
-        fConfirmedDisplayed = false;
-    }
-
-    IMPLEMENT_SERIALIZE
-    (
-        CWalletTx* pthis = const_cast<CWalletTx*>(this);
-        if (fRead)
-            pthis->Init();
-        char fSpent = false;
-
-        if (!fRead)
-        {
-            pthis->mapValue["fromaccount"] = pthis->strFromAccount;
-
-            std::string str;
-            BOOST_FOREACH(char f, vfSpent)
-            {
-                str += (f ? '1' : '0');
-                if (f)
-                    fSpent = true;
-            }
-            pthis->mapValue["spent"] = str;
-        }
-
-        nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
-        READWRITE(vtxPrev);
-        READWRITE(mapValue);
-        READWRITE(vOrderForm);
-        READWRITE(fTimeReceivedIsTxTime);
-        READWRITE(nTimeReceived);
-        READWRITE(fFromMe);
-        READWRITE(fSpent);
-
-        if (fRead)
-        {
-            pthis->strFromAccount = pthis->mapValue["fromaccount"];
-
-            if (mapValue.count("spent"))
-                BOOST_FOREACH(char c, pthis->mapValue["spent"])
-                    pthis->vfSpent.push_back(c != '0');
-            else
-                pthis->vfSpent.assign(vout.size(), fSpent);
-        }
-
-        pthis->mapValue.erase("fromaccount");
-        pthis->mapValue.erase("version");
-        pthis->mapValue.erase("spent");
-    )
-
-    // marks certain txout's as spent
-    // returns true if any update took place
-    bool UpdateSpent(const std::vector<char>& vfNewSpent)
-    {
-        bool fReturn = false;
-        for (int i=0; i < vfNewSpent.size(); i++)
-        {
-            if (i == vfSpent.size())
-                break;
-
-            if (vfNewSpent[i] && !vfSpent[i])
-            {
-                vfSpent[i] = true;
-                fReturn = true;
-                fAvailableCreditCached = false;
-            }
-        }
-        return fReturn;
-    }
-
-    void MarkDirty()
-    {
-        fCreditCached = false;
-        fAvailableCreditCached = false;
-        fDebitCached = false;
-        fChangeCached = false;
-    }
-
-    void MarkSpent(unsigned int nOut)
-    {
-        if (nOut >= vout.size())
-            throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
-        vfSpent.resize(vout.size());
-        if (!vfSpent[nOut])
-        {
-            vfSpent[nOut] = true;
-            fAvailableCreditCached = false;
-        }
-    }
-
-    bool IsSpent(unsigned int nOut) const
-    {
-        if (nOut >= vout.size())
-            throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
-        if (nOut >= vfSpent.size())
-            return false;
-        return (!!vfSpent[nOut]);
-    }
-
-    int64 GetDebit() const
-    {
-        if (vin.empty())
-            return 0;
-        if (fDebitCached)
-            return nDebitCached;
-        nDebitCached = CTransaction::GetDebit();
-        fDebitCached = true;
-        return nDebitCached;
-    }
-
-    int64 GetCredit(bool fUseCache=true) const
-    {
-        // Must wait until coinbase is safely deep enough in the chain before valuing it
-        if (IsCoinBase() && GetBlocksToMaturity() > 0)
-            return 0;
-
-        // GetBalance can assume transactions in mapWallet won't change
-        if (fUseCache && fCreditCached)
-            return nCreditCached;
-        nCreditCached = CTransaction::GetCredit();
-        fCreditCached = true;
-        return nCreditCached;
-    }
-
-    int64 GetAvailableCredit(bool fUseCache=true) const
-    {
-        // Must wait until coinbase is safely deep enough in the chain before valuing it
-        if (IsCoinBase() && GetBlocksToMaturity() > 0)
-            return 0;
-
-        if (fUseCache && fAvailableCreditCached)
-            return nAvailableCreditCached;
-
-        int64 nCredit = 0;
-        for (int i = 0; i < vout.size(); i++)
-        {
-            if (!IsSpent(i))
-            {
-                const CTxOut &txout = vout[i];
-                nCredit += txout.GetCredit();
-                if (!MoneyRange(nCredit))
-                    throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
-            }
-        }
-
-        nAvailableCreditCached = nCredit;
-        fAvailableCreditCached = true;
-        return nCredit;
-    }
-
-
-    int64 GetChange() const
-    {
-        if (fChangeCached)
-            return nChangeCached;
-        nChangeCached = CTransaction::GetChange();
-        fChangeCached = true;
-        return nChangeCached;
-    }
-
-    void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<std::string /* address */, int64> >& listReceived,
-                    std::list<std::pair<std::string /* address */, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
-
-    void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
-                           int64& nSent, int64& nFee) const;
-
-    bool IsFromMe() const
-    {
-        return (GetDebit() > 0);
-    }
-
-    bool IsConfirmed() const
-    {
-        // Quick answer in most cases
-        if (!IsFinal())
-            return false;
-        if (GetDepthInMainChain() >= 1)
-            return true;
-        if (!IsFromMe()) // using wtx's cached debit
-            return false;
-
-        // If no confirmations but it's from us, we can still
-        // consider it confirmed if all dependencies are confirmed
-        std::map<uint256, const CMerkleTx*> mapPrev;
-        std::vector<const CMerkleTx*> vWorkQueue;
-        vWorkQueue.reserve(vtxPrev.size()+1);
-        vWorkQueue.push_back(this);
-        for (int i = 0; i < vWorkQueue.size(); i++)
-        {
-            const CMerkleTx* ptx = vWorkQueue[i];
-
-            if (!ptx->IsFinal())
-                return false;
-            if (ptx->GetDepthInMainChain() >= 1)
-                continue;
-            if (!ptx->IsFromMe())
-                return false;
-
-            if (mapPrev.empty())
-                BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
-                    mapPrev[tx.GetHash()] = &tx;
-
-            BOOST_FOREACH(const CTxIn& txin, ptx->vin)
-            {
-                if (!mapPrev.count(txin.prevout.hash))
-                    return false;
-                vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
-            }
-        }
-        return true;
-    }
-
-    bool WriteToDisk()
-    {
-        return CWalletDB().WriteTx(GetHash(), *this);
-    }
-
-
-    int64 GetTxTime() const;
-    int GetRequestCount() const;
-
-    void AddSupportingTransactions(CTxDB& txdb);
-
-    bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
-    bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
-
-    void RelayWalletTransaction(CTxDB& txdb);
-    void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
+    bool AcceptToMemoryPool();
 };
 
 
@@ -1735,114 +1354,6 @@ public:
 
 
 
-//
-// Private key that includes an expiration date in case it never gets used.
-//
-class CWalletKey
-{
-public:
-    CPrivKey vchPrivKey;
-    int64 nTimeCreated;
-    int64 nTimeExpires;
-    std::string strComment;
-    //// todo: add something to note what created it (user, getnewaddress, change)
-    ////   maybe should have a map<string, string> property map
-
-    CWalletKey(int64 nExpires=0)
-    {
-        nTimeCreated = (nExpires ? GetTime() : 0);
-        nTimeExpires = nExpires;
-    }
-
-    IMPLEMENT_SERIALIZE
-    (
-        if (!(nType & SER_GETHASH))
-            READWRITE(nVersion);
-        READWRITE(vchPrivKey);
-        READWRITE(nTimeCreated);
-        READWRITE(nTimeExpires);
-        READWRITE(strComment);
-    )
-};
-
-
-
-
-
-
-//
-// Account information.
-// Stored in wallet with key "acc"+string account name
-//
-class CAccount
-{
-public:
-    std::vector<unsigned char> vchPubKey;
-
-    CAccount()
-    {
-        SetNull();
-    }
-
-    void SetNull()
-    {
-        vchPubKey.clear();
-    }
-
-    IMPLEMENT_SERIALIZE
-    (
-        if (!(nType & SER_GETHASH))
-            READWRITE(nVersion);
-        READWRITE(vchPubKey);
-    )
-};
-
-
-
-//
-// Internal transfers.
-// Database key is acentry<account><counter>
-//
-class CAccountingEntry
-{
-public:
-    std::string strAccount;
-    int64 nCreditDebit;
-    int64 nTime;
-    std::string strOtherAccount;
-    std::string strComment;
-
-    CAccountingEntry()
-    {
-        SetNull();
-    }
-
-    void SetNull()
-    {
-        nCreditDebit = 0;
-        nTime = 0;
-        strAccount.clear();
-        strOtherAccount.clear();
-        strComment.clear();
-    }
-
-    IMPLEMENT_SERIALIZE
-    (
-        if (!(nType & SER_GETHASH))
-            READWRITE(nVersion);
-        // Note: strAccount is serialized as part of the key, not here.
-        READWRITE(nCreditDebit);
-        READWRITE(nTime);
-        READWRITE(strOtherAccount);
-        READWRITE(strComment);
-    )
-};
-
-
-
-
-
-
 
 
 
@@ -2054,13 +1565,9 @@ public:
 
 
 
+
 extern std::map<uint256, CTransaction> mapTransactions;
-extern std::map<uint256, CWalletTx> mapWallet;
-extern std::vector<uint256> vWalletUpdated;
-extern CCriticalSection cs_mapWallet;
-extern std::map<std::vector<unsigned char>, CPrivKey> mapKeys;
 extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
-extern CCriticalSection cs_mapKeys;
-extern CKey keyUser;
+extern CCriticalSection cs_mapPubKeys;
 
 #endif
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
new file mode 100644 (file)
index 0000000..3fb18ff
--- /dev/null
@@ -0,0 +1,111 @@
+# 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.
+
+DEPSDIR:=/usr/i586-mingw32msvc
+
+INCLUDEPATHS= \
+ -I"$(DEPSDIR)/boost_1_43_0" \
+ -I"$(DEPSDIR)/db-4.7.25.NC/build_unix" \
+ -I"$(DEPSDIR)/openssl-1.0.0d/include" \
+ -I"$(DEPSDIR)/wxWidgets-2.9.1/lib/gcc_lib/mswud" \
+ -I"$(DEPSDIR)/wxWidgets-2.9.1/include" \
+ -I"$(DEPSDIR)/wxWidgets-2.9.1/lib/wx/include/i586-mingw32msvc-msw-unicode-static-2.9/" \
+ -I"$(DEPSDIR)"
+
+LIBPATHS= \
+ -L"$(DEPSDIR)/boost_1_43_0/stage/lib" \
+ -L"$(DEPSDIR)/db-4.7.25.NC/build_unix" \
+ -L"$(DEPSDIR)/openssl-1.0.0d" \
+ -L"$(DEPSDIR)/wxWidgets-2.9.1/lib"
+
+WXLIBS= -l wx_mswu-2.9-i586-mingw32msvc
+
+LIBS= \
+ -l boost_system-mt-s \
+ -l boost_filesystem-mt-s \
+ -l boost_program_options-mt-s \
+ -l boost_thread_win32-mt-s \
+ -l db_cxx \
+ -l ssl \
+ -l crypto
+
+DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
+DEBUGFLAGS=-g -D__WXDEBUG__
+CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(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 keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h
+
+bitcoin.exe: USE_UPNP:=1
+       ifdef USE_UPNP
+               INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
+               LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
+               LIBS += -l miniupnpc -l iphlpapi
+               DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
+       endif
+
+bitcoind.exe: USE_UPNP:=0
+       ifdef USE_UPNP
+               INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
+               LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
+               LIBS += -l miniupnpc -l iphlpapi
+               DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
+       endif
+
+LIBS += -l mingwthrd -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
+
+OBJS= \
+    obj/util.o \
+    obj/script.o \
+    obj/db.o \
+    obj/net.o \
+    obj/irc.o \
+    obj/keystore.o \
+    obj/main.o \
+    obj/wallet.o \
+    obj/rpc.o \
+    obj/init.o \
+    cryptopp/obj/sha.o \
+    cryptopp/obj/cpu.o
+
+
+all: bitcoin.exe
+
+
+obj/%.o: %.cpp $(HEADERS)
+       i586-mingw32msvc-g++ -c $(CFLAGS) -DGUI -o $@ $<
+
+cryptopp/obj/%.o: cryptopp/%.cpp
+       i586-mingw32msvc-g++ -c $(CFLAGS) -O3 -DCRYPTOPP_DISABLE_ASM -o $@ $<
+
+obj/ui_res.o: ../share/ui.rc  ../share/pixmaps/bitcoin.ico ../share/pixmaps/check.ico ../share/pixmaps/send16.bmp ../share/pixmaps/send16mask.bmp ../share/pixmaps/send16masknoshadow.bmp ../share/pixmaps/send20.bmp ../share/pixmaps/send20mask.bmp ../share/pixmaps/addressbook16.bmp ../share/pixmaps/addressbook16mask.bmp ../share/pixmaps/addressbook20.bmp ../share/pixmaps/addressbook20mask.bmp
+       i586-mingw32msvc-windres $(DEFS) $(INCLUDEPATHS) -o $@ -i $<
+
+bitcoin.exe: $(OBJS) obj/ui.o obj/uibase.o obj/ui_res.o
+       i586-mingw32msvc-g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
+
+
+obj/nogui/%.o: %.cpp $(HEADERS)
+       i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
+
+bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/ui_res.o
+       i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
+
+
+obj/test/%.o: obj/test/%.cpp $(HEADERS)
+       i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
+
+test_bitcoin.exe: obj/test/test_bitcoin.o
+       i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework-mt-s
+
+
+clean:
+       -rm -f obj/*.o
+       -rm -f obj/nogui/*.o
+       -rm -f obj/test/*.o
+       -rm -f cryptopp/obj/*.o
+       -rm -f test/*.o
+       -rm -f headers.h.gch
+       -rm -f bitcoin.exe
+       -rm -f bitcoind.exe
+       -rm -f test_bitcoin.exe
index c3a964e..507833b 100644 (file)
@@ -33,7 +33,7 @@ DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
 DEBUGFLAGS=-g -D__WXDEBUG__
 CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(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 noui.h init.h
+    script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h
 
 ifdef USE_UPNP
  INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215"
@@ -50,7 +50,9 @@ OBJS= \
     obj/db.o \
     obj/net.o \
     obj/irc.o \
+    obj/keystore.o \
     obj/main.o \
+    obj/wallet.o \
     obj/rpc.o \
     obj/init.o \
     cryptopp/obj/sha.o \
@@ -79,9 +81,17 @@ obj/nogui/%.o: %.cpp $(HEADERS)
 bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/ui_res.o
        g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
+obj/test/%.o: obj/test/%.cpp $(HEADERS)
+       g++ -c $(CFLAGS) -o $@ $<
+
+test_bitcoin: obj/test/test_bitcoin.o
+       g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
 clean:
+       -del /Q bitcoin bitcoind test_bitcoin
        -del /Q obj\*
        -del /Q obj\nogui\*
+       -del /Q obj\test\*
        -del /Q cryptopp\obj\*
+       -del /Q test\*.o
        -del /Q headers.h.gch
index 4836ea3..784596b 100644 (file)
@@ -33,7 +33,7 @@ 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 -O3 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(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 noui.h init.h
+    script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h
 
 OBJS= \
     obj/util.o \
@@ -41,7 +41,9 @@ OBJS= \
     obj/db.o \
     obj/net.o \
     obj/irc.o \
+    obj/keystore.o \
     obj/main.o \
+    obj/wallet.o \
     obj/rpc.o \
     obj/init.o \
     cryptopp/obj/sha.o \
@@ -72,9 +74,15 @@ obj/nogui/%.o: %.cpp $(HEADERS)
 bitcoind: $(OBJS:obj/%=obj/nogui/%)
        $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
+obj/test/%.o: test/%.cpp $(HEADERS)
+       $(CXX) -c $(CFLAGS) -o $@ $<
+
+test_bitcoin: obj/test/test_bitcoin.o
+       $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework
 
 clean:
-       -rm -f bitcoin bitcoind
+       -rm -f bitcoin bitcoind test_bitcoin
        -rm -f obj/*.o
        -rm -f obj/nogui/*.o
+       -rm -f obj/test/*.o
        -rm -f cryptopp/obj/*.o
index 4f2da37..bb26bf5 100644 (file)
@@ -39,7 +39,7 @@ LIBS+= \
 DEBUGFLAGS=-g -D__WXDEBUG__
 CXXFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS)
 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 noui.h init.h
+    script.h db.h net.h irc.h keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h init.h
 
 OBJS= \
     obj/util.o \
@@ -47,7 +47,9 @@ OBJS= \
     obj/db.o \
     obj/net.o \
     obj/irc.o \
+    obj/keystore.o \
     obj/main.o \
+    obj/wallet.o \
     obj/rpc.o \
     obj/init.o \
     cryptopp/obj/sha.o \
@@ -73,11 +75,16 @@ obj/nogui/%.o: %.cpp $(HEADERS)
 bitcoind: $(OBJS:obj/%=obj/nogui/%)
        $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
 
+obj/test/%.o: test/%.cpp $(HEADERS)
+       $(CXX) -c $(CFLAGS) -o $@ $<
+
+test_bitcoin: obj/test/test_bitcoin.o
+       $(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework
 
 clean:
+       -rm -f bitcoin bitcoind test_bitcoin
        -rm -f obj/*.o
        -rm -f obj/nogui/*.o
+       -rm -f obj/test/*.o
        -rm -f cryptopp/obj/*.o
        -rm -f headers.h.gch
-       -rm -f bitcoin
-       -rm -f bitcoind
index 18ced02..b25ba60 100644 (file)
@@ -8,33 +8,45 @@ INCLUDEPATHS= \
   /I"/db/build_windows" \
   /I"/openssl/include" \
   /I"/wxwidgets/lib/vc_lib/mswu" \
-  /I"/wxwidgets/include"
+  /I"/wxwidgets/include" /
+  /I"/miniupnpc"
 
 LIBPATHS= \
   /LIBPATH:"/boost/stage/lib" \
   /LIBPATH:"/db/build_windows/Release" \
   /LIBPATH:"/openssl/lib" \
   /LIBPATH:"/wxwidgets/lib/vc_lib" \
+  /LIBPATH:"/miniupnpc/msvc/Release" \
   /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib \
   /NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib \
   /NODEFAULTLIB:msvcrtd.lib
 
 WXLIBS=wxmsw29u.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib
 
+USE_UPNP=0
+
+DEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH /DNOMINMAX
+
 LIBS= \
   libboost_system-vc100-mt.lib \
   libboost_filesystem-vc100-mt.lib \
   libboost_program_options-vc100-mt.lib \
   libboost_thread-vc100-mt.lib \
   libdb47s.lib \
-  libeay32.lib \
+  libeay32.lib
+
+!IFDEF USE_UPNP
+LIBS=$(LIBS) miniupnpc.lib
+DEFS=$(DEFS) /DUSE_UPNP=$(USE_UPNP)
+!ENDIF
+
+LIBS=$(LIBS) \
   kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
 
-DEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
 DEBUGFLAGS=/Os
 CFLAGS=/MD /c /nologo /EHsc /GR /Zm300 $(DEBUGFLAGS) $(DEFS) $(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 noui.h init.h
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h wallet.h keystore.h
 
 OBJS= \
     obj\util.obj \
@@ -42,12 +54,18 @@ OBJS= \
     obj\db.obj \
     obj\net.obj \
     obj\irc.obj \
+       obj\keystore.obj \
     obj\main.obj \
+       obj\wallet.obj \
     obj\rpc.obj \
-    obj\init.obj \
+    obj\init.obj
+
+CRYPTOPP_OBJS= \
     cryptopp\obj\sha.obj \
     cryptopp\obj\cpu.obj
 
+RC=../share
+
 
 all: bitcoin.exe
 
@@ -65,8 +83,12 @@ obj\net.obj: $(HEADERS)
 
 obj\irc.obj: $(HEADERS)
 
+obj\keystore.obj: $(HEADERS)
+
 obj\main.obj: $(HEADERS)
 
+obj\wallet.obj: $(HEADERS)
+
 obj\rpc.obj: $(HEADERS)
 
 obj\init.obj: $(HEADERS)
@@ -81,13 +103,13 @@ cryptopp\obj\sha.obj: cryptopp\sha.cpp
 cryptopp\obj\cpu.obj: cryptopp\cpu.cpp
     cl $(CFLAGS) /O2 /DCRYPTOPP_DISABLE_ASM /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
+obj\ui.res: $(RC)/ui.rc $(RC)/pixmaps/bitcoin.ico $(RC)/pixmaps/check.ico $(RC)/pixmaps/send16.bmp $(RC)/pixmaps/send16mask.bmp $(RC)/pixmaps/send16masknoshadow.bmp $(RC)/pixmaps/send20.bmp $(RC)/pixmaps/send20mask.bmp $(RC)/pixmaps/addressbook16.bmp $(RC)/pixmaps/addressbook16mask.bmp $(RC)/pixmaps/addressbook20.bmp $(RC)/pixmaps/addressbook20mask.bmp
     rc $(INCLUDEPATHS) $(DEFS) /Fo$@ %s
 
-bitcoin.exe: $(OBJS) obj\ui.obj obj\uibase.obj obj\ui.res
+bitcoin.exe: $(OBJS) $(CRYPTOPP_OBJS) obj\ui.obj obj\uibase.obj obj\ui.res
     link /nologo /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(WXLIBS) $(LIBS)
 
-
+       
 .cpp{obj\nogui}.obj:
     cl $(CFLAGS) /Fo$@ %s
 
@@ -101,13 +123,17 @@ obj\nogui\net.obj: $(HEADERS)
 
 obj\nogui\irc.obj: $(HEADERS)
 
+obj\nogui\keystore.obj: $(HEADERS)
+
 obj\nogui\main.obj: $(HEADERS)
 
+obj\nogui\wallet.obj: $(HEADERS)
+
 obj\nogui\rpc.obj: $(HEADERS)
 
 obj\nogui\init.obj: $(HEADERS)
 
-bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\ui.res
+bitcoind.exe: $(OBJS:obj\=obj\nogui\) $(CRYPTOPP_OBJS) obj\ui.res
     link /nologo /OUT:$@ $(LIBPATHS) $** $(LIBS)
 
 
index c884e8d..0d3348d 100644 (file)
@@ -3,6 +3,20 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "irc.h"
+#include "db.h"
+#include "net.h"
+#include "init.h"
+#include "strlcpy.h"
+
+#ifdef __WXMSW__
+#include <string.h>
+// This file can be downloaded as a part of the Windows Platform SDK
+// and is required for Bitcoin binaries to work properly on versions
+// of Windows before XP.  If you are doing builds of Bitcoin for
+// public release, you should uncomment this line.
+//#include <WSPiApi.h>
+#endif
 
 #ifdef USE_UPNP
 #include <miniupnpc/miniwget.h>
@@ -51,6 +65,7 @@ map<CInv, int64> mapAlreadyAskedFor;
 
 // Settings
 int fUseProxy = false;
+int nConnectTimeout = 5000;
 CAddress addrProxy("127.0.0.1",9050);
 
 
@@ -76,7 +91,7 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
 
 
 
-bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
+bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
 {
     hSocketRet = INVALID_SOCKET;
 
@@ -91,8 +106,87 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
 
+#ifdef __WXMSW__
+    u_long fNonblock = 1;
+    if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
+#else
+    int fFlags = fcntl(hSocket, F_GETFL, 0);
+    if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
+#endif
+    {
+        closesocket(hSocket);
+        return false;
+    }
+
+
     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
     {
+        // WSAEINVAL is here because some legacy version of winsock uses it
+        if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
+        {
+            struct timeval timeout;
+            timeout.tv_sec  = nTimeout / 1000;
+            timeout.tv_usec = (nTimeout % 1000) * 1000;
+
+            fd_set fdset;
+            FD_ZERO(&fdset);
+            FD_SET(hSocket, &fdset);
+            int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
+            if (nRet == 0)
+            {
+                printf("connection timeout\n");
+                closesocket(hSocket);
+                return false;
+            }
+            if (nRet == SOCKET_ERROR)
+            {
+                printf("select() for connection failed: %i\n",WSAGetLastError());
+                closesocket(hSocket);
+                return false;
+            }
+            socklen_t nRetSize = sizeof(nRet);
+#ifdef __WXMSW__
+            if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
+#else
+            if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
+#endif
+            {
+                printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
+                closesocket(hSocket);
+                return false;
+            }
+            if (nRet != 0)
+            {
+                printf("connect() failed after select(): %s\n",strerror(nRet));
+                closesocket(hSocket);
+                return false;
+            }
+        }
+#ifdef __WXMSW__
+        else if (WSAGetLastError() != WSAEISCONN)
+#else
+        else
+#endif
+        {
+            printf("connect() failed: %i\n",WSAGetLastError());
+            closesocket(hSocket);
+            return false;
+        }
+    }
+
+    /*
+    this isn't even strictly necessary
+    CNode::ConnectNode immediately turns the socket back to non-blocking
+    but we'll turn it back to blocking just in case
+    */
+#ifdef __WXMSW__
+    fNonblock = 0;
+    if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
+#else
+    fFlags = fcntl(hSocket, F_GETFL, 0);
+    if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
+#endif
+    {
         closesocket(hSocket);
         return false;
     }
@@ -830,7 +924,7 @@ void ThreadSocketHandler2(void* parg)
                     CDataStream& vRecv = pnode->vRecv;
                     unsigned int nPos = vRecv.size();
 
-                    if (nPos > 1000*GetArg("-maxreceivebuffer", 10*1000)) {
+                    if (nPos > ReceiveBufferSize()) {
                         if (!pnode->fDisconnect)
                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
                         pnode->CloseSocketDisconnect();
@@ -895,7 +989,7 @@ void ThreadSocketHandler2(void* parg)
                                 pnode->CloseSocketDisconnect();
                             }
                         }
-                        if (vSend.size() > 1000*GetArg("-maxsendbuffer", 10*1000)) {
+                        if (vSend.size() > SendBufferSize()) {
                             if (!pnode->fDisconnect)
                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
                             pnode->CloseSocketDisconnect();
@@ -1032,7 +1126,7 @@ void MapPort(bool fMapPort)
     if (fUseUPnP != fMapPort)
     {
         fUseUPnP = fMapPort;
-        CWalletDB().WriteSetting("fUseUPnP", fUseUPnP);
+        WriteSetting("fUseUPnP", fUseUPnP);
     }
     if (fUseUPnP && vnThreadsRunning[5] < 1)
     {
@@ -1054,25 +1148,29 @@ void MapPort(bool fMapPort)
 static const char *strDNSSeed[] = {
     "bitseed.xf2.org",
     "bitseed.bitcoin.org.uk",
+    "dnsseed.bluematt.me",
 };
 
 void DNSAddressSeed()
 {
     int found = 0;
 
-    printf("Loading addresses from DNS seeds (could take a while)\n");
+    if (!fTestNet)
+    {
+        printf("Loading addresses from DNS seeds (could take a while)\n");
 
-    for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
-        vector<CAddress> vaddr;
-        if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
-        {
-            BOOST_FOREACH (CAddress& addr, vaddr)
+        for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
+            vector<CAddress> vaddr;
+            if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
             {
-                if (addr.GetByte(3) != 127)
+                BOOST_FOREACH (CAddress& addr, vaddr)
                 {
-                    addr.nTime = 0;
-                    AddAddress(addr);
-                    found++;
+                    if (addr.GetByte(3) != 127)
+                    {
+                        addr.nTime = 0;
+                        AddAddress(addr);
+                        found++;
+                    }
                 }
             }
         }
@@ -1613,7 +1711,7 @@ void StartNode(void* parg)
         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
 
     // Generate coins in the background
-    GenerateBitcoins(fGenerateBitcoins);
+    GenerateBitcoins(fGenerateBitcoins, pwalletMain);
 }
 
 bool StopNode()
index d1ded87..afa264b 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -19,9 +19,12 @@ class CRequestTracker;
 class CNode;
 class CBlockIndex;
 extern int nBestHeight;
+extern int nConnectTimeout;
 
 
 
+inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
+inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
 inline unsigned short GetDefaultPort() { return fTestNet ? 18333 : 8333; }
 static const unsigned int PUBLISH_HOPS = 5;
 enum
@@ -32,7 +35,7 @@ enum
 
 
 
-bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
+bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
 bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
 bool GetMyExternalIP(unsigned int& ipRet);
index afb1952..d0072df 100644 (file)
@@ -5,6 +5,8 @@
 #define BITCOIN_NOUI_H
 
 #include <string>
+#include <boost/function.hpp>
+#include "wallet.h"
 
 typedef void wxWindow;
 #define wxYES                   0x00000002
diff --git a/src/obj/test/.gitignore b/src/obj/test/.gitignore
new file mode 100644 (file)
index 0000000..d6b7ef3
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!.gitignore
index 530bef4..6f951b7 100644 (file)
@@ -4,12 +4,18 @@
 
 #include "headers.h"
 #include "cryptopp/sha.h"
+#include "db.h"
+#include "net.h"
+#include "init.h"
 #undef printf
 #include <boost/asio.hpp>
 #include <boost/iostreams/concepts.hpp>
 #include <boost/iostreams/stream.hpp>
+#include <boost/algorithm/string.hpp>
 #ifdef USE_SSL
 #include <boost/asio/ssl.hpp> 
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
 #endif
 #include "json/json_spirit_reader_template.h"
@@ -259,14 +265,14 @@ Value setgenerate(const Array& params, bool fHelp)
     {
         int nGenProcLimit = params[1].get_int();
         fLimitProcessors = (nGenProcLimit != -1);
-        CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
+        WriteSetting("fLimitProcessors", fLimitProcessors);
         if (nGenProcLimit != -1)
-            CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
+            WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
         if (nGenProcLimit == 0)
             fGenerate = false;
     }
 
-    GenerateBitcoins(fGenerate);
+    GenerateBitcoins(fGenerate, pwalletMain);
     return Value::null;
 }
 
@@ -293,7 +299,7 @@ Value getinfo(const Array& params, bool fHelp)
 
     Object obj;
     obj.push_back(Pair("version",       (int)VERSION));
-    obj.push_back(Pair("balance",       ValueFromAmount(GetBalance())));
+    obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
     obj.push_back(Pair("blocks",        (int)nBestHeight));
     obj.push_back(Pair("connections",   (int)vNodes.size()));
     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
@@ -302,7 +308,7 @@ Value getinfo(const Array& params, bool fHelp)
     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
     obj.push_back(Pair("testnet",       fTestNet));
-    obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
+    obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
     return obj;
@@ -324,19 +330,22 @@ Value getnewaddress(const Array& params, bool fHelp)
         strAccount = AccountFromValue(params[0]);
 
     // Generate a new key that is added to wallet
-    string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+    string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
+
+    // This could be done in the same main CS as GetKeyFromKeyPool.
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+       pwalletMain->SetAddressBookName(strAddress, strAccount);
 
-    SetAddressBookName(strAddress, strAccount);
     return strAddress;
 }
 
 
-// requires cs_main, cs_mapWallet locks
+// requires cs_main, cs_mapWallet, cs_mapAddressBook locks
 string GetAccountAddress(string strAccount, bool bForceNew=false)
 {
     string strAddress;
 
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
     walletdb.TxnBegin();
 
     CAccount account;
@@ -347,8 +356,8 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
     {
         CScript scriptPubKey;
         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
-             it != mapWallet.end() && !account.vchPubKey.empty();
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
+             it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
              ++it)
         {
             const CWalletTx& wtx = (*it).second;
@@ -361,9 +370,9 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
     // Generate a new key
     if (account.vchPubKey.empty() || bForceNew)
     {
-        account.vchPubKey = GetKeyFromKeyPool();
+        account.vchPubKey = pwalletMain->GetKeyFromKeyPool();
         string strAddress = PubKeyToAddress(account.vchPubKey);
-        SetAddressBookName(strAddress, strAccount);
+        pwalletMain->SetAddressBookName(strAddress, strAccount);
         walletdb.WriteAccount(strAccount, account);
     }
 
@@ -386,7 +395,8 @@ Value getaccountaddress(const Array& params, bool fHelp)
     Value ret;
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         ret = GetAccountAddress(strAccount);
     }
@@ -416,18 +426,19 @@ Value setaccount(const Array& params, bool fHelp)
 
     // Detect when changing the account of an address that is the 'unused current key' of another account:
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        if (mapAddressBook.count(strAddress))
+        if (pwalletMain->mapAddressBook.count(strAddress))
         {
-            string strOldAccount = mapAddressBook[strAddress];
+            string strOldAccount = pwalletMain->mapAddressBook[strAddress];
             if (strAddress == GetAccountAddress(strOldAccount))
                 GetAccountAddress(strOldAccount, true);
         }
+
+        pwalletMain->SetAddressBookName(strAddress, strAccount);
     }
 
-    SetAddressBookName(strAddress, strAccount);
     return Value::null;
 }
 
@@ -442,10 +453,10 @@ Value getaccount(const Array& params, bool fHelp)
     string strAddress = params[0].get_str();
 
     string strAccount;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        map<string, string>::iterator mi = mapAddressBook.find(strAddress);
-        if (mi != mapAddressBook.end() && !(*mi).second.empty())
+        map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+        if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
             strAccount = (*mi).second;
     }
     return strAccount;
@@ -463,9 +474,9 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
 
     // Find all addresses that have the given account
     Array ret;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strName = item.second;
@@ -518,7 +529,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
 
     CRITICAL_BLOCK(cs_main)
     {
-        string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
+        string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
         if (strError != "")
             throw JSONRPCError(-4, strError);
     }
@@ -539,7 +550,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
     CScript scriptPubKey;
     if (!scriptPubKey.SetBitcoinAddress(strAddress))
         throw JSONRPCError(-5, "Invalid bitcoin address");
-    if (!IsMine(scriptPubKey))
+    if (!IsMine(*pwalletMain,scriptPubKey))
         return (double)0.0;
 
     // Minimum confirmations
@@ -549,9 +560,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
 
     // Tally
     int64 nAmount = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -570,9 +581,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
 
 void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
 {
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strName = item.second;
@@ -581,7 +592,7 @@ void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
                 // We're only counting our own valid bitcoin addresses and not ip addresses
                 CScript scriptPubKey;
                 if (scriptPubKey.SetBitcoinAddress(strAddress))
-                    if (IsMine(scriptPubKey))
+                    if (IsMine(*pwalletMain,scriptPubKey))
                         setPubKey.insert(scriptPubKey);
             }
         }
@@ -608,9 +619,9 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
 
     // Tally
     int64 nAmount = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -630,10 +641,10 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
 {
     int64 nBalance = 0;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Tally wallet transactions
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (!wtx.IsFinal())
@@ -656,7 +667,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
 
 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
 {
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
     return GetAccountBalance(walletdb, strAccount, nMinDepth);
 }
 
@@ -670,7 +681,7 @@ Value getbalance(const Array& params, bool fHelp)
             "If [account] is specified, returns the balance in the account.");
 
     if (params.size() == 0)
-        return  ValueFromAmount(GetBalance());
+        return  ValueFromAmount(pwalletMain->GetBalance());
 
     int nMinDepth = 1;
     if (params.size() > 1)
@@ -681,7 +692,7 @@ Value getbalance(const Array& params, bool fHelp)
         // (GetBalance() sums up all unspent TxOuts)
         // getbalance and getbalance '*' should always return the same number.
         int64 nBalance = 0;
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (!wtx.IsFinal())
@@ -729,9 +740,9 @@ Value movecmd(const Array& params, bool fHelp)
     if (params.size() > 4)
         strComment = params[4].get_str();
 
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        CWalletDB walletdb;
+        CWalletDB walletdb(pwalletMain->strWalletFile);
         walletdb.TxnBegin();
 
         int64 nNow = GetAdjustedTime();
@@ -782,7 +793,7 @@ Value sendfrom(const Array& params, bool fHelp)
         wtx.mapValue["to"]      = params[5].get_str();
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Check funds
         int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -790,7 +801,7 @@ Value sendfrom(const Array& params, bool fHelp)
             throw JSONRPCError(-6, "Account has insufficient funds");
 
         // Send
-        string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
+        string strError = pwalletMain->SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
         if (strError != "")
             throw JSONRPCError(-4, strError);
     }
@@ -839,7 +850,7 @@ Value sendmany(const Array& params, bool fHelp)
     }
 
     CRITICAL_BLOCK(cs_main)
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Check funds
         int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
@@ -847,16 +858,16 @@ Value sendmany(const Array& params, bool fHelp)
             throw JSONRPCError(-6, "Account has insufficient funds");
 
         // Send
-        CReserveKey keyChange;
+        CReserveKey keyChange(pwalletMain);
         int64 nFeeRequired = 0;
-        bool fCreated = CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
+        bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
         if (!fCreated)
         {
-            if (totalAmount + nFeeRequired > GetBalance())
+            if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
                 throw JSONRPCError(-6, "Insufficient funds");
             throw JSONRPCError(-4, "Transaction creation failed");
         }
-        if (!CommitTransaction(wtx, keyChange))
+        if (!pwalletMain->CommitTransaction(wtx, keyChange))
             throw JSONRPCError(-4, "Transaction commit failed");
     }
 
@@ -889,9 +900,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
 
     // Tally
     map<uint160, tallyitem> mapTally;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             if (wtx.IsCoinBase() || !wtx.IsFinal())
@@ -918,9 +929,9 @@ Value ListReceived(const Array& params, bool fByAccounts)
     // Reply
     Array ret;
     map<string, tallyitem> mapAccountTally;
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             const string& strAddress = item.first;
             const string& strAccount = item.second;
@@ -1056,13 +1067,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
 
     // Received
     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
-        CRITICAL_BLOCK(cs_mapAddressBook)
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
             BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
             {
                 string account;
-                if (mapAddressBook.count(r.first))
-                    account = mapAddressBook[r.first];
+                if (pwalletMain->mapAddressBook.count(r.first))
+                    account = pwalletMain->mapAddressBook[r.first];
                 if (fAllAccounts || (account == strAccount))
                 {
                     Object entry;
@@ -1114,16 +1125,16 @@ Value listtransactions(const Array& params, bool fHelp)
         nFrom = params[2].get_int();
 
     Array ret;
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
 
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
         typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
         typedef multimap<int64, TxPair > TxItems;
         TxItems txByTime;
 
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             CWalletTx* wtx = &((*it).second);
             txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
@@ -1175,16 +1186,16 @@ Value listaccounts(const Array& params, bool fHelp)
         nMinDepth = params[0].get_int();
 
     map<string, int64> mapAccountBalances;
-    CRITICAL_BLOCK(cs_mapWallet)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& entry, mapAddressBook) {
+        BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
             uint160 hash160;
             if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
                 mapAccountBalances[entry.second] = 0;
         }
 
-        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
         {
             const CWalletTx& wtx = (*it).second;
             int64 nGeneratedImmature, nGeneratedMature, nFee;
@@ -1199,8 +1210,8 @@ Value listaccounts(const Array& params, bool fHelp)
             {
                 mapAccountBalances[""] += nGeneratedMature;
                 BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
-                    if (mapAddressBook.count(r.first))
-                        mapAccountBalances[mapAddressBook[r.first]] += r.second;
+                    if (pwalletMain->mapAddressBook.count(r.first))
+                        mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
                     else
                         mapAccountBalances[""] += r.second;
             }
@@ -1208,7 +1219,7 @@ Value listaccounts(const Array& params, bool fHelp)
     }
 
     list<CAccountingEntry> acentries;
-    CWalletDB().ListAccountCreditDebit("*", acentries);
+    CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
 
@@ -1230,11 +1241,11 @@ Value gettransaction(const Array& params, bool fHelp)
     hash.SetHex(params[0].get_str());
 
     Object entry;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        if (!mapWallet.count(hash))
+        if (!pwalletMain->mapWallet.count(hash))
             throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
-        const CWalletTx& wtx = mapWallet[hash];
+        const CWalletTx& wtx = pwalletMain->mapWallet[hash];
 
         int64 nCredit = wtx.GetCredit();
         int64 nDebit = wtx.GetDebit();
@@ -1245,10 +1256,10 @@ Value gettransaction(const Array& params, bool fHelp)
         if (wtx.IsFromMe())
             entry.push_back(Pair("fee", ValueFromAmount(nFee)));
 
-        WalletTxToJSON(mapWallet[hash], entry);
+        WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
 
         Array details;
-        ListTransactions(mapWallet[hash], "*", 0, false, details);
+        ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
         entry.push_back(Pair("details", details));
     }
 
@@ -1264,7 +1275,7 @@ Value backupwallet(const Array& params, bool fHelp)
             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
 
     string strDest = params[0].get_str();
-    BackupWallet(strDest);
+    BackupWallet(*pwalletMain, strDest);
 
     return Value::null;
 }
@@ -1290,10 +1301,10 @@ Value validateaddress(const Array& params, bool fHelp)
         string currentAddress = Hash160ToAddress(hash160);
         ret.push_back(Pair("address", currentAddress));
         ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
-        CRITICAL_BLOCK(cs_mapAddressBook)
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
-            if (mapAddressBook.count(currentAddress))
-                ret.push_back(Pair("account", mapAddressBook[currentAddress]));
+            if (pwalletMain->mapAddressBook.count(currentAddress))
+                ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
         }
     }
     return ret;
@@ -1320,7 +1331,7 @@ Value getwork(const Array& params, bool fHelp)
 
     static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
     static vector<CBlock*> vNewBlock;
-    static CReserveKey reservekey;
+    static CReserveKey reservekey(pwalletMain);
 
     if (params.size() == 0)
     {
@@ -1401,7 +1412,7 @@ Value getwork(const Array& params, bool fHelp)
         pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
 
-        return CheckWork(pblock, reservekey);
+        return CheckWork(pblock, *pwalletMain, reservekey);
     }
 }
 
@@ -1526,7 +1537,7 @@ string rfc1123Time()
     return string(buffer);
 }
 
-string HTTPReply(int nStatus, const string& strMsg)
+static string HTTPReply(int nStatus, const string& strMsg)
 {
     if (nStatus == 401)
         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
@@ -1548,6 +1559,7 @@ string HTTPReply(int nStatus, const string& strMsg)
     string strStatus;
          if (nStatus == 200) strStatus = "OK";
     else if (nStatus == 400) strStatus = "Bad Request";
+    else if (nStatus == 403) strStatus = "Forbidden";
     else if (nStatus == 404) strStatus = "Not Found";
     else if (nStatus == 500) strStatus = "Internal Server Error";
     return strprintf(
@@ -1881,7 +1893,12 @@ void ThreadRPCServer2(void* parg)
 
         // Restrict callers by IP
         if (!ClientAllowed(peer.address().to_string()))
+        {
+            // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
+            if (!fUseSSL)
+                stream << HTTPReply(403, "") << std::flush;
             continue;
+        }
 
         map<string, string> mapHeaders;
         string strRequest;
index 97334ca..bd1b5b3 100644 (file)
@@ -1021,7 +1021,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
 }
 
 
-bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
 {
     scriptSigRet.clear();
 
@@ -1030,7 +1030,7 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
         return false;
 
     // Compile solution
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(keystore.cs_mapKeys)
     {
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
@@ -1038,12 +1038,13 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
             {
                 // Sign
                 const valtype& vchPubKey = item.second;
-                if (!mapKeys.count(vchPubKey))
+                CPrivKey privkey;
+                if (!keystore.GetPrivKey(vchPubKey, privkey))
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!CKey::Sign(privkey, hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
                     scriptSigRet << vchSig;
@@ -1056,12 +1057,13 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
                 if (mi == mapPubKeys.end())
                     return false;
                 const vector<unsigned char>& vchPubKey = (*mi).second;
-                if (!mapKeys.count(vchPubKey))
+                CPrivKey privkey;
+                if (!keystore.GetPrivKey(vchPubKey, privkey))
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!CKey::Sign(privkey, hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
                     scriptSigRet << vchSig << vchPubKey;
@@ -1085,14 +1087,14 @@ bool IsStandard(const CScript& scriptPubKey)
 }
 
 
-bool IsMine(const CScript& scriptPubKey)
+bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
 {
     CScript scriptSig;
-    return Solver(scriptPubKey, 0, 0, scriptSig);
+    return Solver(keystore, scriptPubKey, 0, 0, scriptSig);
 }
 
 
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
+bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vector<unsigned char>& vchPubKeyRet)
 {
     vchPubKeyRet.clear();
 
@@ -1100,7 +1102,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
     if (!Solver(scriptPubKey, vSolution))
         return false;
 
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(cs_mapPubKeys)
     {
         BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
@@ -1116,7 +1118,7 @@ bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned
                     continue;
                 vchPubKey = (*mi).second;
             }
-            if (!fMineOnly || mapKeys.count(vchPubKey))
+            if (keystore == NULL || keystore->HaveKey(vchPubKey))
             {
                 vchPubKeyRet = vchPubKey;
                 return true;
@@ -1160,7 +1162,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
 }
 
 
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
 {
     assert(nIn < txTo.vin.size());
     CTxIn& txin = txTo.vin[nIn];
@@ -1171,7 +1173,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
     // The checksig op will also drop the signatures from its hash.
     uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
 
-    if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
+    if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig))
         return false;
 
     txin.scriptSig = scriptPrereq + txin.scriptSig;
@@ -1199,10 +1201,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
     if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
         return false;
 
-    // Anytime a signature is successfully verified, it's proof the outpoint is spent,
-    // so lets update the wallet spent flag if it doesn't know due to wallet.dat being
-    // restored from backup or the user making copies of wallet.dat.
-    WalletUpdateSpent(txin.prevout);
-
     return true;
 }
index 22a6020..ae9fdff 100644 (file)
@@ -5,6 +5,7 @@
 #define H_BITCOIN_SCRIPT
 
 #include "base58.h"
+#include "keystore.h"
 
 #include <string>
 #include <vector>
@@ -707,12 +708,11 @@ public:
 
 
 
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
 bool IsStandard(const CScript& scriptPubKey);
-bool IsMine(const CScript& scriptPubKey);
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet);
+bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
+bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet);
 bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
+bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
 bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
 
 #endif
index 0d66d6a..31862a7 100644 (file)
@@ -33,7 +33,7 @@ class CDataStream;
 class CAutoFile;
 static const unsigned int MAX_SIZE = 0x02000000;
 
-static const int VERSION = 32300;
+static const int VERSION = 32400;
 static const char* pszSubVer = "";
 static const bool VERSION_IS_BETA = true;
 
diff --git a/src/test/README b/src/test/README
new file mode 100644 (file)
index 0000000..77f7faa
--- /dev/null
@@ -0,0 +1,21 @@
+The sources in this directory are unit test cases.  Boost includes a
+unit testing framework, and since bitcoin already uses boost, it makes
+sense to simply use this framework rather than require developers to
+configure some other framework (we want as few impediments to creating
+unit tests as possible).
+
+The build system is setup to compile an executable called "test_bitcoin"
+that runs all of the unit tests.  The main source file is called
+test_bitcoin.cpp, which simply includes other files that contain the
+actual unit tests (outside of a couple required preprocessor
+directives).  The pattern is to create one test file for each class or
+source file for which you want to create unit tests.  The file naming
+convention is "<source_filename>_tests.cpp" and such files should wrap
+their tests in a test suite called "<source_filename>_tests".  For an
+examples of this pattern, examine uint160_tests.cpp and
+uint256_tests.cpp.
+
+For further reading, I found the following website to be helpful in
+explaining how the boost unit test framework works:
+
+http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
new file mode 100644 (file)
index 0000000..3b7d2d2
--- /dev/null
@@ -0,0 +1,6 @@
+#define BOOST_TEST_MODULE uint160
+#include <boost/test/unit_test.hpp>
+
+#include "uint160_tests.cpp"
+#include "uint256_tests.cpp"
+
diff --git a/src/test/uint160_tests.cpp b/src/test/uint160_tests.cpp
new file mode 100644 (file)
index 0000000..66ffd28
--- /dev/null
@@ -0,0 +1,16 @@
+#include "../uint256.h"
+
+BOOST_AUTO_TEST_SUITE(uint160_tests)
+
+BOOST_AUTO_TEST_CASE(equality)
+{
+    uint160 num1 = 10;
+    uint160 num2 = 11;
+    BOOST_CHECK(num1+1 == num2);
+
+    uint64 num3 = 10;
+    BOOST_CHECK(num1 == num3);
+    BOOST_CHECK(num1+num2 == num3+num2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
new file mode 100644 (file)
index 0000000..cbae9bf
--- /dev/null
@@ -0,0 +1,16 @@
+#include "../uint256.h"
+
+BOOST_AUTO_TEST_SUITE(uint256_tests)
+
+BOOST_AUTO_TEST_CASE(equality)
+{
+    uint256 num1 = 10;
+    uint256 num2 = 11;
+    BOOST_CHECK(num1+1 == num2);
+
+    uint64 num3 = 10;
+    BOOST_CHECK(num1 == num3);
+    BOOST_CHECK(num1+num2 == num3+num2);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
index cca473d..9b84fb9 100644 (file)
@@ -3,6 +3,11 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
+#include "db.h"
+#include "init.h"
+#include "strlcpy.h"
+#include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/convenience.hpp>
 #ifdef _MSC_VER
 #include <crtdbg.h>
 #endif
@@ -235,7 +240,7 @@ void SetDefaultReceivingAddress(const string& strAddress)
             return;
         if (!mapPubKeys.count(hash160))
             return;
-        CWalletDB().WriteDefaultKey(mapPubKeys[hash160]);
+        pwalletMain->SetDefaultKey(mapPubKeys[hash160]);
         pframeMain->m_textCtrlAddress->SetValue(strAddress);
     }
 }
@@ -285,7 +290,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     dResize = 1.22;
     SetSize(dResize * GetSize().GetWidth(), 1.15 * GetSize().GetHeight());
 #endif
-    m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+    m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
     m_listCtrl->SetFocus();
     ptaskbaricon = new CMyTaskBarIcon();
 #ifdef __WXMAC_OSX__
@@ -325,7 +330,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
 
     // Fill your address text box
     vector<unsigned char> vchPubKey;
-    if (CWalletDB("r").ReadDefaultKey(vchPubKey))
+    if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey))
         m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey));
 
     // Fill listctrl with wallet transactions
@@ -620,7 +625,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             {
                 int64 nUnmatured = 0;
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    nUnmatured += txout.GetCredit();
+                    nUnmatured += pwalletMain->GetCredit(txout);
                 if (wtx.IsInMainChain())
                 {
                     strDescription = strprintf(_("Generated (%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -656,19 +661,19 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 return false;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
             {
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                 {
                     vector<unsigned char> vchPubKey;
-                    if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                    if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                     {
-                        CRITICAL_BLOCK(cs_mapAddressBook)
+                        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
                         {
                             //strDescription += _("Received payment to ");
                             //strDescription += _("Received with address ");
                             strDescription += _("Received with: ");
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            map<string, string>::iterator mi = mapAddressBook.find(strAddress);
-                            if (mi != mapAddressBook.end() && !(*mi).second.empty())
+                            map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+                            if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
                             {
                                 string strLabel = (*mi).second;
                                 strDescription += strAddress.substr(0,12) + "... ";
@@ -698,11 +703,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
     {
         bool fAllFromMe = true;
         BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-            fAllFromMe = fAllFromMe && txin.IsMine();
+            fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
         bool fAllToMe = true;
         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-            fAllToMe = fAllToMe && txout.IsMine();
+            fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
         if (fAllFromMe && fAllToMe)
         {
@@ -728,7 +733,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
             {
                 const CTxOut& txout = wtx.vout[nOut];
-                if (txout.IsMine())
+                if (pwalletMain->IsMine(txout))
                     continue;
 
                 string strAddress;
@@ -746,9 +751,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 }
 
                 string strDescription = _("To: ");
-                CRITICAL_BLOCK(cs_mapAddressBook)
-                    if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                        strDescription += mapAddressBook[strAddress] + " ";
+                CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+                    if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                        strDescription += pwalletMain->mapAddressBook[strAddress] + " ";
                 strDescription += strAddress;
                 if (!mapValue["message"].empty())
                 {
@@ -787,9 +792,9 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
             //
             bool fAllMine = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllMine = fAllMine && txout.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txout);
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllMine = fAllMine && txin.IsMine();
+                fAllMine = fAllMine && pwalletMain->IsMine(txin);
 
             InsertLine(fNew, nIndex, hash, strSort, colour,
                        strStatus,
@@ -816,16 +821,16 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         // Collect list of wallet transactions and sort newest first
         bool fEntered = false;
         vector<pair<unsigned int, uint256> > vSorted;
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             printf("RefreshListCtrl starting\n");
             fEntered = true;
             fRefreshListCtrl = false;
-            vWalletUpdated.clear();
+            pwalletMain->vWalletUpdated.clear();
 
             // Do the newest transactions first
-            vSorted.reserve(mapWallet.size());
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            vSorted.reserve(pwalletMain->mapWallet.size());
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 const CWalletTx& wtx = (*it).second;
                 unsigned int nTime = UINT_MAX - wtx.GetTxTime();
@@ -844,12 +849,12 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
             if (fShutdown)
                 return;
             bool fEntered = false;
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 fEntered = true;
                 uint256& hash = vSorted[i++].second;
-                map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                if (mi != mapWallet.end())
+                map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                if (mi != pwalletMain->mapWallet.end())
                     InsertTransaction((*mi).second, true);
             }
             if (!fEntered || i == 100 || i % 500 == 0)
@@ -867,10 +872,10 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
         static int64 nLastTime;
         if (GetTime() > nLastTime + 30)
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 nLastTime = GetTime();
-                for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+                for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
                 {
                     CWalletTx& wtx = (*it).second;
                     if (wtx.nTimeDisplayed && wtx.nTimeDisplayed != wtx.GetTxTime())
@@ -891,7 +896,7 @@ void CMainFrame::RefreshStatusColumn()
     if (nTop == nLastTop && pindexLastBest == pindexBest)
         return;
 
-    TRY_CRITICAL_BLOCK(cs_mapWallet)
+    TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         int nStart = nTop;
         int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
@@ -911,8 +916,8 @@ void CMainFrame::RefreshStatusColumn()
         for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
         {
             uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
-            map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-            if (mi == mapWallet.end())
+            map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+            if (mi == pwalletMain->mapWallet.end())
             {
                 printf("CMainFrame::RefreshStatusColumn() : tx not found in mapWallet\n");
                 continue;
@@ -1009,41 +1014,41 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
         nLastRepaintTime = GetTimeMillis();
 
         // Update listctrl contents
-        if (!vWalletUpdated.empty())
+        if (!pwalletMain->vWalletUpdated.empty())
         {
-            TRY_CRITICAL_BLOCK(cs_mapWallet)
+            TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 string strTop;
                 if (m_listCtrl->GetItemCount())
                     strTop = (string)m_listCtrl->GetItemText(0);
-                BOOST_FOREACH(uint256 hash, vWalletUpdated)
+                BOOST_FOREACH(uint256 hash, pwalletMain->vWalletUpdated)
                 {
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+                    if (mi != pwalletMain->mapWallet.end())
                         InsertTransaction((*mi).second, false);
                 }
-                vWalletUpdated.clear();
+                pwalletMain->vWalletUpdated.clear();
                 if (m_listCtrl->GetItemCount() && strTop != (string)m_listCtrl->GetItemText(0))
                     m_listCtrl->ScrollList(0, INT_MIN/2);
             }
         }
 
         // Balance total
-        TRY_CRITICAL_BLOCK(cs_mapWallet)
+        TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
         {
             fPaintedBalance = true;
-            m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
+            m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + "  ");
 
             // Count hidden and multi-line transactions
             nTransactionCount = 0;
-            for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+            for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
             {
                 CWalletTx& wtx = (*it).second;
                 nTransactionCount += wtx.nLinesDisplayed;
             }
         }
     }
-    if (!vWalletUpdated.empty() || !fPaintedBalance)
+    if (!pwalletMain->vWalletUpdated.empty() || !fPaintedBalance)
         nNeedRepaint++;
 
     // Update status column of visible items only
@@ -1069,7 +1074,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     m_statusBar->SetStatusText(strStatus, 2);
 
     // Update receiving address
-    string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
+    string strDefaultAddress = PubKeyToAddress(pwalletMain->vchDefaultKey);
     if (m_textCtrlAddress->GetValue() != strDefaultAddress)
         m_textCtrlAddress->SetValue(strDefaultAddress);
 }
@@ -1178,10 +1183,11 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
     string strName = dialog.GetValue();
 
     // Generate new key
-    string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+    string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
 
     // Save
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, strName);
     SetDefaultReceivingAddress(strAddress);
 }
 
@@ -1199,10 +1205,10 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
 {
     uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
     CWalletTx wtx;
-    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
-        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
-        if (mi == mapWallet.end())
+        map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
+        if (mi == pwalletMain->mapWallet.end())
         {
             printf("CMainFrame::OnListItemActivated() : tx not found in mapWallet\n");
             return;
@@ -1230,7 +1236,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
 #ifdef __WXMSW__
     SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
 #endif
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strHTML;
         strHTML.reserve(4000);
@@ -1280,19 +1286,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Credit
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                     {
                         vector<unsigned char> vchPubKey;
-                        if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
+                        if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
                         {
                             string strAddress = PubKeyToAddress(vchPubKey);
-                            if (mapAddressBook.count(strAddress))
+                            if (pwalletMain->mapAddressBook.count(strAddress))
                             {
                                 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
                                 strHTML += _("<b>To:</b> ");
                                 strHTML += HtmlEscape(strAddress);
-                                if (!mapAddressBook[strAddress].empty())
-                                    strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
+                                if (!pwalletMain->mapAddressBook[strAddress].empty())
+                                    strHTML += _(" (yours, label: ") + pwalletMain->mapAddressBook[strAddress] + ")";
                                 else
                                     strHTML += _(" (yours)");
                                 strHTML += "<br>";
@@ -1314,8 +1320,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             // Online transaction
             strAddress = wtx.mapValue["to"];
             strHTML += _("<b>To:</b> ");
-            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                strHTML += mapAddressBook[strAddress] + " ";
+            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
             strHTML += HtmlEscape(strAddress) + "<br>";
         }
 
@@ -1330,7 +1336,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             //
             int64 nUnmatured = 0;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                nUnmatured += txout.GetCredit();
+                nUnmatured += pwalletMain->GetCredit(txout);
             strHTML += _("<b>Credit:</b> ");
             if (wtx.IsInMainChain())
                 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
@@ -1349,11 +1355,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             bool fAllFromMe = true;
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                fAllFromMe = fAllFromMe && txin.IsMine();
+                fAllFromMe = fAllFromMe && pwalletMain->IsMine(txin);
 
             bool fAllToMe = true;
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                fAllToMe = fAllToMe && txout.IsMine();
+                fAllToMe = fAllToMe && pwalletMain->IsMine(txout);
 
             if (fAllFromMe)
             {
@@ -1362,7 +1368,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 //
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 {
-                    if (txout.IsMine())
+                    if (pwalletMain->IsMine(txout))
                         continue;
 
                     if (wtx.mapValue["to"].empty())
@@ -1373,8 +1379,8 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                         {
                             string strAddress = Hash160ToAddress(hash160);
                             strHTML += _("<b>To:</b> ");
-                            if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
-                                strHTML += mapAddressBook[strAddress] + " ";
+                            if (pwalletMain->mapAddressBook.count(strAddress) && !pwalletMain->mapAddressBook[strAddress].empty())
+                                strHTML += pwalletMain->mapAddressBook[strAddress] + " ";
                             strHTML += strAddress;
                             strHTML += "<br>";
                         }
@@ -1402,11 +1408,11 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
                 // Mixed debit transaction
                 //
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                    if (txin.IsMine())
-                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
+                    if (pwalletMain->IsMine(txin))
+                        strHTML += _("<b>Debit:</b> ") + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                    if (txout.IsMine())
-                        strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
+                    if (pwalletMain->IsMine(txout))
+                        strHTML += _("<b>Credit:</b> ") + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
             }
         }
 
@@ -1432,30 +1438,30 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
         {
             strHTML += "<hr><br>debug print<br><br>";
             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
-                if (txin.IsMine())
-                    strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
+                if (pwalletMain->IsMine(txin))
+                    strHTML += "<b>Debit:</b> " + FormatMoney(-pwalletMain->GetDebit(txin)) + "<br>";
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                if (txout.IsMine())
-                    strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
+                if (pwalletMain->IsMine(txout))
+                    strHTML += "<b>Credit:</b> " + FormatMoney(pwalletMain->GetCredit(txout)) + "<br>";
 
             strHTML += "<br><b>Transaction:</b><br>";
             strHTML += HtmlEscape(wtx.ToString(), true);
 
             strHTML += "<br><b>Inputs:</b><br>";
-            CRITICAL_BLOCK(cs_mapWallet)
+            CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
             {
                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
                 {
                     COutPoint prevout = txin.prevout;
-                    map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
-                    if (mi != mapWallet.end())
+                    map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(prevout.hash);
+                    if (mi != pwalletMain->mapWallet.end())
                     {
                         const CWalletTx& prev = (*mi).second;
                         if (prevout.n < prev.vout.size())
                         {
                             strHTML += HtmlEscape(prev.ToString(), true);
                             strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", ";
-                            strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
+                            strHTML = strHTML + "IsMine=" + (pwalletMain->IsMine(prev.vout[prevout.n]) ? "true" : "false") + "<br>";
                         }
                     }
                 }
@@ -1746,7 +1752,7 @@ void COptionsDialog::OnButtonCancel(wxCommandEvent& event)
 
 void COptionsDialog::OnButtonApply(wxCommandEvent& event)
 {
-    CWalletDB walletdb;
+    CWalletDB walletdb(pwalletMain->strWalletFile);
 
     int64 nPrevTransactionFee = nTransactionFee;
     if (ParseMoney(m_textCtrlTransactionFee->GetValue(), nTransactionFee) && nTransactionFee != nPrevTransactionFee)
@@ -1923,12 +1929,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
             wxMessageBox(_("Error in amount  "), _("Send Coins"));
             return;
         }
-        if (nValue > GetBalance())
+        if (nValue > pwalletMain->GetBalance())
         {
             wxMessageBox(_("Amount exceeds your balance  "), _("Send Coins"));
             return;
         }
-        if (nValue + nTransactionFee > GetBalance())
+        if (nValue + nTransactionFee > pwalletMain->GetBalance())
         {
             wxMessageBox(string(_("Total exceeds your balance when the ")) + FormatMoney(nTransactionFee) + _(" transaction fee is included  "), _("Send Coins"));
             return;
@@ -1946,7 +1952,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
                 CScript scriptPubKey;
                 scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
 
-                string strError = SendMoney(scriptPubKey, nValue, wtx, true);
+                string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
                 if (strError == "")
                     wxMessageBox(_("Payment sent  "), _("Sending..."));
                 else if (strError == "ABORTED")
@@ -1978,9 +1984,9 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
                 return;
         }
 
-        CRITICAL_BLOCK(cs_mapAddressBook)
-            if (!mapAddressBook.count(strAddress))
-                SetAddressBookName(strAddress, "");
+        CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+            if (!pwalletMain->mapAddressBook.count(strAddress))
+                pwalletMain->SetAddressBookName(strAddress, "");
 
         EndModal(true);
     }
@@ -2164,7 +2170,7 @@ void SendingDialogStartTransfer(void* parg)
 void CSendingDialog::StartTransfer()
 {
     // Make sure we have enough money
-    if (nPrice + nTransactionFee > GetBalance())
+    if (nPrice + nTransactionFee > pwalletMain->GetBalance())
     {
         Error(_("Insufficient funds"));
         return;
@@ -2235,16 +2241,16 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
         // Pay
         if (!Status(_("Creating transaction...")))
             return;
-        if (nPrice + nTransactionFee > GetBalance())
+        if (nPrice + nTransactionFee > pwalletMain->GetBalance())
         {
             Error(_("Insufficient funds"));
             return;
         }
-        CReserveKey reservekey;
+        CReserveKey reservekey(pwalletMain);
         int64 nFeeRequired;
-        if (!CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
+        if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
         {
-            if (nPrice + nFeeRequired > GetBalance())
+            if (nPrice + nFeeRequired > pwalletMain->GetBalance())
                 Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
             else
                 Error(_("Transaction creation failed"));
@@ -2282,7 +2288,7 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
             return;
 
         // Commit
-        if (!CommitTransaction(wtx, reservekey))
+        if (!pwalletMain->CommitTransaction(wtx, reservekey))
         {
             Error(_("The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
             return;
@@ -2376,11 +2382,11 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
     m_listCtrlReceiving->SetFocus();
 
     // Fill listctrl with address book data
-    CRITICAL_BLOCK(cs_mapKeys)
-    CRITICAL_BLOCK(cs_mapAddressBook)
+    CRITICAL_BLOCK(pwalletMain->cs_mapKeys)
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
         string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
         {
             string strAddress = item.first;
             string strName = item.second;
@@ -2439,7 +2445,8 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
     if (event.IsEditCancelled())
         return;
     string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
-    SetAddressBookName(strAddress, string(event.GetText()));
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
     pframeMain->RefreshListCtrl();
 }
 
@@ -2474,7 +2481,8 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
         if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
         {
             string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
-            CWalletDB().EraseName(strAddress);
+            CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+                pwalletMain->DelAddressBookName(strAddress);
             m_listCtrl->DeleteItem(nIndex);
         }
     }
@@ -2533,9 +2541,12 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
     }
 
     // Write back
-    if (strAddress != strAddressOrg)
-        CWalletDB().EraseName(strAddressOrg);
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+    {
+        if (strAddress != strAddressOrg)
+            pwalletMain->DelAddressBookName(strAddressOrg);
+        pwalletMain->SetAddressBookName(strAddress, strName);
+    }
     m_listCtrl->SetItem(nIndex, 1, strAddress);
     m_listCtrl->SetItemText(nIndex, strName);
     pframeMain->RefreshListCtrl();
@@ -2571,11 +2582,12 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
         strName = dialog.GetValue();
 
         // Generate new key
-        strAddress = PubKeyToAddress(GetKeyFromKeyPool());
+        strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool());
     }
 
     // Add to list and select it
-    SetAddressBookName(strAddress, strName);
+    CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+        pwalletMain->SetAddressBookName(strAddress, strName);
     int nIndex = InsertLine(m_listCtrl, strName, strAddress);
     SetSelection(m_listCtrl, nIndex);
     m_listCtrl->SetFocus();
index 16643db..3f06ad9 100644 (file)
--- a/src/ui.h
+++ b/src/ui.h
@@ -4,6 +4,9 @@
 #ifndef BITCOIN_UI_H
 #define BITCOIN_UI_H
 
+#include <boost/function.hpp>
+#include "wallet.h"
+
 DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1)
 
 
index 5220cdc..479c601 100644 (file)
@@ -2,6 +2,14 @@
 // 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"
+#include "strlcpy.h"
+#include <boost/program_options/detail/config_file.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/foreach.hpp>
 
 using namespace std;
 using namespace boost;
@@ -338,11 +346,6 @@ string FormatMoney(int64 n, bool fPlus)
     if (nTrim)
         str.erase(str.size()-nTrim, nTrim);
 
-    // Insert thousands-separators:
-    size_t point = str.find(".");
-    for (int i = (str.size()-point)+3; i < str.size(); i += 4)
-        if (isdigit(str[str.size() - i - 1]))
-            str.insert(str.size() - i, 1, ',');
     if (n < 0)
         str.insert((unsigned int)0, 1, '-');
     else if (fPlus && n > 0)
@@ -365,8 +368,6 @@ bool ParseMoney(const char* pszIn, int64& nRet)
         p++;
     for (; *p; p++)
     {
-        if (*p == ',' && p > pszIn && isdigit(p[-1]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]) && !isdigit(p[4]))
-            continue;
         if (*p == '.')
         {
             p++;
@@ -895,8 +896,10 @@ string FormatVersion(int nVersion)
 string FormatFullVersion()
 {
     string s = FormatVersion(VERSION) + pszSubVer;
-    if (VERSION_IS_BETA)
-        s += "-" + _("beta");
+    if (VERSION_IS_BETA) {
+        s += "-";
+        s += _("beta");
+    }
     return s;
 }
 
index e4bf0fb..e711057 100644 (file)
@@ -15,7 +15,6 @@
 #include <vector>
 #include <string>
 
-#include <boost/foreach.hpp>
 #include <boost/thread.hpp>
 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
 #include <boost/date_time/gregorian/gregorian_types.hpp>
@@ -105,6 +104,8 @@ T* alignup(T* p)
 typedef int socklen_t;
 #else
 #define WSAGetLastError()   errno
+#define WSAEINVAL           EINVAL
+#define WSAEALREADY         EALREADY
 #define WSAEWOULDBLOCK      EWOULDBLOCK
 #define WSAEMSGSIZE         EMSGSIZE
 #define WSAEINTR            EINTR
diff --git a/src/wallet.cpp b/src/wallet.cpp
new file mode 100644 (file)
index 0000000..6ef75ef
--- /dev/null
@@ -0,0 +1,1139 @@
+// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
+// 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"
+#include "db.h"
+#include "cryptopp/sha.h"
+
+using namespace std;
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// mapWallet
+//
+
+bool CWallet::AddKey(const CKey& key)
+{
+    this->CKeyStore::AddKey(key);
+    if (!fFileBacked)
+        return true;
+    return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
+}
+
+void CWallet::WalletUpdateSpent(const CTransaction &tx)
+{
+    // Anytime a signature is successfully verified, it's proof the outpoint is spent.
+    // Update the wallet spent flag if it doesn't know due to wallet.dat being
+    // restored from backup or the user making copies of wallet.dat.
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        BOOST_FOREACH(const CTxIn& txin, tx.vin)
+        {
+            map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
+            if (mi != mapWallet.end())
+            {
+                CWalletTx& wtx = (*mi).second;
+                if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
+                {
+                    printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+                    wtx.MarkSpent(txin.prevout.n);
+                    wtx.WriteToDisk();
+                    vWalletUpdated.push_back(txin.prevout.hash);
+                }
+            }
+        }
+    }
+}
+
+bool CWallet::AddToWallet(const CWalletTx& wtxIn)
+{
+    uint256 hash = wtxIn.GetHash();
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        // Inserts only if not already there, returns tx inserted or tx found
+        pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
+        CWalletTx& wtx = (*ret.first).second;
+        wtx.pwallet = this;
+        bool fInsertedNew = ret.second;
+        if (fInsertedNew)
+            wtx.nTimeReceived = GetAdjustedTime();
+
+        bool fUpdated = false;
+        if (!fInsertedNew)
+        {
+            // Merge
+            if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
+            {
+                wtx.hashBlock = wtxIn.hashBlock;
+                fUpdated = true;
+            }
+            if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
+            {
+                wtx.vMerkleBranch = wtxIn.vMerkleBranch;
+                wtx.nIndex = wtxIn.nIndex;
+                fUpdated = true;
+            }
+            if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
+            {
+                wtx.fFromMe = wtxIn.fFromMe;
+                fUpdated = true;
+            }
+            fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
+        }
+
+        //// debug print
+        printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+
+        // Write to disk
+        if (fInsertedNew || fUpdated)
+            if (!wtx.WriteToDisk())
+                return false;
+
+        // If default receiving address gets used, replace it with a new one
+        CScript scriptDefaultKey;
+        scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
+        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+        {
+            if (txout.scriptPubKey == scriptDefaultKey)
+                SetDefaultKey(GetKeyFromKeyPool());
+        }
+
+        // Notify UI
+        vWalletUpdated.push_back(hash);
+
+        // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
+        WalletUpdateSpent(wtx);
+    }
+
+    // Refresh UI
+    MainFrameRepaint();
+    return true;
+}
+
+bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+{
+    uint256 hash = tx.GetHash();
+    bool fExisted = mapWallet.count(hash);
+    if (fExisted && !fUpdate) return false;
+    if (fExisted || IsMine(tx) || IsFromMe(tx))
+    {
+        CWalletTx wtx(this,tx);
+        // Get merkle branch if transaction was found in a block
+        if (pblock)
+            wtx.SetMerkleBranch(pblock);
+        return AddToWallet(wtx);
+    }
+    else
+        WalletUpdateSpent(tx);
+    return false;
+}
+
+bool CWallet::EraseFromWallet(uint256 hash)
+{
+    if (!fFileBacked)
+        return false;
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        if (mapWallet.erase(hash))
+            CWalletDB(strWalletFile).EraseTx(hash);
+    }
+    return true;
+}
+
+
+bool CWallet::IsMine(const CTxIn &txin) const
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+        if (mi != mapWallet.end())
+        {
+            const CWalletTx& prev = (*mi).second;
+            if (txin.prevout.n < prev.vout.size())
+                if (IsMine(prev.vout[txin.prevout.n]))
+                    return true;
+        }
+    }
+    return false;
+}
+
+int64 CWallet::GetDebit(const CTxIn &txin) const
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+        if (mi != mapWallet.end())
+        {
+            const CWalletTx& prev = (*mi).second;
+            if (txin.prevout.n < prev.vout.size())
+                if (IsMine(prev.vout[txin.prevout.n]))
+                    return prev.vout[txin.prevout.n].nValue;
+        }
+    }
+    return 0;
+}
+
+int64 CWalletTx::GetTxTime() const
+{
+    if (!fTimeReceivedIsTxTime && hashBlock != 0)
+    {
+        // If we did not receive the transaction directly, we rely on the block's
+        // time to figure out when it happened.  We use the median over a range
+        // of blocks to try to filter out inaccurate block times.
+        map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+        if (mi != mapBlockIndex.end())
+        {
+            CBlockIndex* pindex = (*mi).second;
+            if (pindex)
+                return pindex->GetMedianTime();
+        }
+    }
+    return nTimeReceived;
+}
+
+int CWalletTx::GetRequestCount() const
+{
+    // Returns -1 if it wasn't being tracked
+    int nRequests = -1;
+    CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
+    {
+        if (IsCoinBase())
+        {
+            // Generated block
+            if (hashBlock != 0)
+            {
+                map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                if (mi != pwallet->mapRequestCount.end())
+                    nRequests = (*mi).second;
+            }
+        }
+        else
+        {
+            // Did anyone request this transaction?
+            map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
+            if (mi != pwallet->mapRequestCount.end())
+            {
+                nRequests = (*mi).second;
+
+                // How about the block it's in?
+                if (nRequests == 0 && hashBlock != 0)
+                {
+                    map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                    if (mi != pwallet->mapRequestCount.end())
+                        nRequests = (*mi).second;
+                    else
+                        nRequests = 1; // If it's in someone else's block it must have got out
+                }
+            }
+        }
+    }
+    return nRequests;
+}
+
+void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<string, int64> >& listReceived,
+                           list<pair<string, int64> >& listSent, int64& nFee, string& strSentAccount) const
+{
+    nGeneratedImmature = nGeneratedMature = nFee = 0;
+    listReceived.clear();
+    listSent.clear();
+    strSentAccount = strFromAccount;
+
+    if (IsCoinBase())
+    {
+        if (GetBlocksToMaturity() > 0)
+            nGeneratedImmature = pwallet->GetCredit(*this);
+        else
+            nGeneratedMature = GetCredit();
+        return;
+    }
+
+    // Compute fee:
+    int64 nDebit = GetDebit();
+    if (nDebit > 0) // debit>0 means we signed/sent this transaction
+    {
+        int64 nValueOut = GetValueOut();
+        nFee = nDebit - nValueOut;
+    }
+
+    // Sent/received.  Standard client will never generate a send-to-multiple-recipients,
+    // but non-standard clients might (so return a list of address/amount pairs)
+    BOOST_FOREACH(const CTxOut& txout, vout)
+    {
+        string address;
+        uint160 hash160;
+        vector<unsigned char> vchPubKey;
+        if (ExtractHash160(txout.scriptPubKey, hash160))
+            address = Hash160ToAddress(hash160);
+        else if (ExtractPubKey(txout.scriptPubKey, NULL, vchPubKey))
+            address = PubKeyToAddress(vchPubKey);
+        else
+        {
+            printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+                   this->GetHash().ToString().c_str());
+            address = " unknown ";
+        }
+
+        // Don't report 'change' txouts
+        if (nDebit > 0 && pwallet->IsChange(txout))
+            continue;
+
+        if (nDebit > 0)
+            listSent.push_back(make_pair(address, txout.nValue));
+
+        if (pwallet->IsMine(txout))
+            listReceived.push_back(make_pair(address, txout.nValue));
+    }
+
+}
+
+void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived, 
+                                  int64& nSent, int64& nFee) const
+{
+    nGenerated = nReceived = nSent = nFee = 0;
+
+    int64 allGeneratedImmature, allGeneratedMature, allFee;
+    allGeneratedImmature = allGeneratedMature = allFee = 0;
+    string strSentAccount;
+    list<pair<string, int64> > listReceived;
+    list<pair<string, int64> > listSent;
+    GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
+
+    if (strAccount == "")
+        nGenerated = allGeneratedMature;
+    if (strAccount == strSentAccount)
+    {
+        BOOST_FOREACH(const PAIRTYPE(string,int64)& s, listSent)
+            nSent += s.second;
+        nFee = allFee;
+    }
+    CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
+    {
+        BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
+        {
+            if (pwallet->mapAddressBook.count(r.first))
+            {
+                map<string, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
+                if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
+                    nReceived += r.second;
+            }
+            else if (strAccount.empty())
+            {
+                nReceived += r.second;
+            }
+        }
+    }
+}
+
+void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
+{
+    vtxPrev.clear();
+
+    const int COPY_DEPTH = 3;
+    if (SetMerkleBranch() < COPY_DEPTH)
+    {
+        vector<uint256> vWorkQueue;
+        BOOST_FOREACH(const CTxIn& txin, vin)
+            vWorkQueue.push_back(txin.prevout.hash);
+
+        // This critsect is OK because txdb is already open
+        CRITICAL_BLOCK(pwallet->cs_mapWallet)
+        {
+            map<uint256, const CMerkleTx*> mapWalletPrev;
+            set<uint256> setAlreadyDone;
+            for (int i = 0; i < vWorkQueue.size(); i++)
+            {
+                uint256 hash = vWorkQueue[i];
+                if (setAlreadyDone.count(hash))
+                    continue;
+                setAlreadyDone.insert(hash);
+
+                CMerkleTx tx;
+                map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
+                if (mi != pwallet->mapWallet.end())
+                {
+                    tx = (*mi).second;
+                    BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
+                        mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
+                }
+                else if (mapWalletPrev.count(hash))
+                {
+                    tx = *mapWalletPrev[hash];
+                }
+                else if (!fClient && txdb.ReadDiskTx(hash, tx))
+                {
+                    ;
+                }
+                else
+                {
+                    printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
+                    continue;
+                }
+
+                int nDepth = tx.SetMerkleBranch();
+                vtxPrev.push_back(tx);
+
+                if (nDepth < COPY_DEPTH)
+                    BOOST_FOREACH(const CTxIn& txin, tx.vin)
+                        vWorkQueue.push_back(txin.prevout.hash);
+            }
+        }
+    }
+
+    reverse(vtxPrev.begin(), vtxPrev.end());
+}
+
+bool CWalletTx::WriteToDisk()
+{
+    return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
+}
+
+int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
+{
+    int ret = 0;
+
+    CBlockIndex* pindex = pindexStart;
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        while (pindex)
+        {
+            CBlock block;
+            block.ReadFromDisk(pindex, true);
+            BOOST_FOREACH(CTransaction& tx, block.vtx)
+            {
+                if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+                    ret++;
+            }
+            pindex = pindex->pnext;
+        }
+    }
+    return ret;
+}
+
+void CWallet::ReacceptWalletTransactions()
+{
+    CTxDB txdb("r");
+    bool fRepeat = true;
+    while (fRepeat) CRITICAL_BLOCK(cs_mapWallet)
+    {
+        fRepeat = false;
+        vector<CDiskTxPos> vMissingTx;
+        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+        {
+            CWalletTx& wtx = item.second;
+            if (wtx.IsCoinBase() && wtx.IsSpent(0))
+                continue;
+
+            CTxIndex txindex;
+            bool fUpdated = false;
+            if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
+            {
+                // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
+                if (txindex.vSpent.size() != wtx.vout.size())
+                {
+                    printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
+                    continue;
+                }
+                for (int i = 0; i < txindex.vSpent.size(); i++)
+                {
+                    if (wtx.IsSpent(i))
+                        continue;
+                    if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
+                    {
+                        wtx.MarkSpent(i);
+                        fUpdated = true;
+                        vMissingTx.push_back(txindex.vSpent[i]);
+                    }
+                }
+                if (fUpdated)
+                {
+                    printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+                    wtx.MarkDirty();
+                    wtx.WriteToDisk();
+                }
+            }
+            else
+            {
+                // Reaccept any txes of ours that aren't already in a block
+                if (!wtx.IsCoinBase())
+                    wtx.AcceptWalletTransaction(txdb, false);
+            }
+        }
+        if (!vMissingTx.empty())
+        {
+            // TODO: optimize this to scan just part of the block chain?
+            if (ScanForWalletTransactions(pindexGenesisBlock))
+                fRepeat = true;  // Found missing transactions: re-do Reaccept.
+        }
+    }
+}
+
+void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
+{
+    BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
+    {
+        if (!tx.IsCoinBase())
+        {
+            uint256 hash = tx.GetHash();
+            if (!txdb.ContainsTx(hash))
+                RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
+        }
+    }
+    if (!IsCoinBase())
+    {
+        uint256 hash = GetHash();
+        if (!txdb.ContainsTx(hash))
+        {
+            printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
+            RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
+        }
+    }
+}
+
+void CWalletTx::RelayWalletTransaction()
+{
+   CTxDB txdb("r");
+   RelayWalletTransaction(txdb);
+}
+
+void CWallet::ResendWalletTransactions()
+{
+    // Do this infrequently and randomly to avoid giving away
+    // that these are our transactions.
+    static int64 nNextTime;
+    if (GetTime() < nNextTime)
+        return;
+    bool fFirst = (nNextTime == 0);
+    nNextTime = GetTime() + GetRand(30 * 60);
+    if (fFirst)
+        return;
+
+    // Only do it if there's been a new block since last time
+    static int64 nLastTime;
+    if (nTimeBestReceived < nLastTime)
+        return;
+    nLastTime = GetTime();
+
+    // Rebroadcast any of our txes that aren't in a block yet
+    printf("ResendWalletTransactions()\n");
+    CTxDB txdb("r");
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        // Sort them in chronological order
+        multimap<unsigned int, CWalletTx*> mapSorted;
+        BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+        {
+            CWalletTx& wtx = item.second;
+            // Don't rebroadcast until it's had plenty of time that
+            // it should have gotten in already by now.
+            if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
+                mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
+        }
+        BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
+        {
+            CWalletTx& wtx = *item.second;
+            wtx.RelayWalletTransaction(txdb);
+        }
+    }
+}
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Actions
+//
+
+
+int64 CWallet::GetBalance() const
+{
+    int64 nStart = GetTimeMillis();
+
+    int64 nTotal = 0;
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+        {
+            const CWalletTx* pcoin = &(*it).second;
+            if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+                continue;
+            nTotal += pcoin->GetAvailableCredit();
+        }
+    }
+
+    //printf("GetBalance() %"PRI64d"ms\n", GetTimeMillis() - nStart);
+    return nTotal;
+}
+
+
+bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
+{
+    setCoinsRet.clear();
+    nValueRet = 0;
+
+    // List of values less than target
+    pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
+    coinLowestLarger.first = INT64_MAX;
+    coinLowestLarger.second.first = NULL;
+    vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
+    int64 nTotalLower = 0;
+
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+       vector<const CWalletTx*> vCoins;
+       vCoins.reserve(mapWallet.size());
+       for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+           vCoins.push_back(&(*it).second);
+       random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
+
+       BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
+       {
+            if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+                continue;
+
+            if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+                continue;
+
+            int nDepth = pcoin->GetDepthInMainChain();
+            if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
+                continue;
+
+            for (int i = 0; i < pcoin->vout.size(); i++)
+            {
+                if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
+                    continue;
+
+                int64 n = pcoin->vout[i].nValue;
+
+                if (n <= 0)
+                    continue;
+
+                pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
+
+                if (n == nTargetValue)
+                {
+                    setCoinsRet.insert(coin.second);
+                    nValueRet += coin.first;
+                    return true;
+                }
+                else if (n < nTargetValue + CENT)
+                {
+                    vValue.push_back(coin);
+                    nTotalLower += n;
+                }
+                else if (n < coinLowestLarger.first)
+                {
+                    coinLowestLarger = coin;
+                }
+            }
+        }
+    }
+
+    if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
+    {
+        for (int i = 0; i < vValue.size(); ++i)
+        {
+            setCoinsRet.insert(vValue[i].second);
+            nValueRet += vValue[i].first;
+        }
+        return true;
+    }
+
+    if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
+    {
+        if (coinLowestLarger.second.first == NULL)
+            return false;
+        setCoinsRet.insert(coinLowestLarger.second);
+        nValueRet += coinLowestLarger.first;
+        return true;
+    }
+
+    if (nTotalLower >= nTargetValue + CENT)
+        nTargetValue += CENT;
+
+    // Solve subset sum by stochastic approximation
+    sort(vValue.rbegin(), vValue.rend());
+    vector<char> vfIncluded;
+    vector<char> vfBest(vValue.size(), true);
+    int64 nBest = nTotalLower;
+
+    for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
+    {
+        vfIncluded.assign(vValue.size(), false);
+        int64 nTotal = 0;
+        bool fReachedTarget = false;
+        for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
+        {
+            for (int i = 0; i < vValue.size(); i++)
+            {
+                if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
+                {
+                    nTotal += vValue[i].first;
+                    vfIncluded[i] = true;
+                    if (nTotal >= nTargetValue)
+                    {
+                        fReachedTarget = true;
+                        if (nTotal < nBest)
+                        {
+                            nBest = nTotal;
+                            vfBest = vfIncluded;
+                        }
+                        nTotal -= vValue[i].first;
+                        vfIncluded[i] = false;
+                    }
+                }
+            }
+        }
+    }
+
+    // If the next larger is still closer, return it
+    if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
+    {
+        setCoinsRet.insert(coinLowestLarger.second);
+        nValueRet += coinLowestLarger.first;
+    }
+    else {
+        for (int i = 0; i < vValue.size(); i++)
+            if (vfBest[i])
+            {
+                setCoinsRet.insert(vValue[i].second);
+                nValueRet += vValue[i].first;
+            }
+
+        //// debug print
+        printf("SelectCoins() best subset: ");
+        for (int i = 0; i < vValue.size(); i++)
+            if (vfBest[i])
+                printf("%s ", FormatMoney(vValue[i].first).c_str());
+        printf("total %s\n", FormatMoney(nBest).c_str());
+    }
+
+    return true;
+}
+
+bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
+{
+    return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
+            SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
+            SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
+}
+
+
+
+
+bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+{
+    int64 nValue = 0;
+    BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
+    {
+        if (nValue < 0)
+            return false;
+        nValue += s.second;
+    }
+    if (vecSend.empty() || nValue < 0)
+        return false;
+
+    wtxNew.pwallet = this;
+
+    CRITICAL_BLOCK(cs_main)
+    {
+        // txdb must be opened before the mapWallet lock
+        CTxDB txdb("r");
+        CRITICAL_BLOCK(cs_mapWallet)
+        {
+            nFeeRet = nTransactionFee;
+            loop
+            {
+                wtxNew.vin.clear();
+                wtxNew.vout.clear();
+                wtxNew.fFromMe = true;
+
+                int64 nTotalValue = nValue + nFeeRet;
+                double dPriority = 0;
+                // vouts to the payees
+                BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
+                    wtxNew.vout.push_back(CTxOut(s.second, s.first));
+
+                // Choose coins to use
+                set<pair<const CWalletTx*,unsigned int> > setCoins;
+                int64 nValueIn = 0;
+                if (!SelectCoins(nTotalValue, setCoins, nValueIn))
+                    return false;
+                BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
+                {
+                    int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
+                    dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
+                }
+
+                // Fill a vout back to self with any change
+                int64 nChange = nValueIn - nTotalValue;
+                if (nChange >= CENT)
+                {
+                    // Note: We use a new key here to keep it from being obvious which side is the change.
+                    //  The drawback is that by not reusing a previous key, the change may be lost if a
+                    //  backup is restored, if the backup doesn't have the new private key for the change.
+                    //  If we reused the old key, it would be possible to add code to look for and
+                    //  rediscover unknown transactions that were written with keys of ours to recover
+                    //  post-backup change.
+
+                    // Reserve a new key pair from key pool
+                    vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
+                    assert(mapKeys.count(vchPubKey));
+
+                    // Fill a vout to ourself, using same address type as the payment
+                    CScript scriptChange;
+                    if (vecSend[0].first.GetBitcoinAddressHash160() != 0)
+                        scriptChange.SetBitcoinAddress(vchPubKey);
+                    else
+                        scriptChange << vchPubKey << OP_CHECKSIG;
+
+                    // Insert change txn at random position:
+                    vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
+                    wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
+                }
+                else
+                    reservekey.ReturnKey();
+
+                // Fill vin
+                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+                    wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
+
+                // Sign
+                int nIn = 0;
+                BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+                    if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
+                        return false;
+
+                // Limit size
+                unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
+                if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
+                    return false;
+                dPriority /= nBytes;
+
+                // Check that enough fee is included
+                int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
+                bool fAllowFree = CTransaction::AllowFree(dPriority);
+                int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
+                if (nFeeRet < max(nPayFee, nMinFee))
+                {
+                    nFeeRet = max(nPayFee, nMinFee);
+                    continue;
+                }
+
+                // Fill vtxPrev by copying from previous transactions vtxPrev
+                wtxNew.AddSupportingTransactions(txdb);
+                wtxNew.fTimeReceivedIsTxTime = true;
+
+                break;
+            }
+        }
+    }
+    return true;
+}
+
+bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
+{
+    vector< pair<CScript, int64> > vecSend;
+    vecSend.push_back(make_pair(scriptPubKey, nValue));
+    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
+}
+
+// Call after CreateTransaction unless you want to abort
+bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
+{
+    CRITICAL_BLOCK(cs_main)
+    {
+        printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
+        CRITICAL_BLOCK(cs_mapWallet)
+        {
+            // This is only to keep the database open to defeat the auto-flush for the
+            // duration of this scope.  This is the only place where this optimization
+            // maybe makes sense; please don't do it anywhere else.
+            CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
+
+            // Take key pair from key pool so it won't be used again
+            reservekey.KeepKey();
+
+            // Add tx to wallet, because if it has change it's also ours,
+            // otherwise just for transaction history.
+            AddToWallet(wtxNew);
+
+            // Mark old coins as spent
+            set<CWalletTx*> setCoins;
+            BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
+            {
+                CWalletTx &coin = mapWallet[txin.prevout.hash];
+                coin.pwallet = this;
+                coin.MarkSpent(txin.prevout.n);
+                coin.WriteToDisk();
+                vWalletUpdated.push_back(coin.GetHash());
+            }
+
+            if (fFileBacked)
+                delete pwalletdb;
+        }
+
+        // Track how many getdata requests our transaction gets
+        CRITICAL_BLOCK(cs_mapRequestCount)
+            mapRequestCount[wtxNew.GetHash()] = 0;
+
+        // Broadcast
+        if (!wtxNew.AcceptToMemoryPool())
+        {
+            // This must not fail. The transaction has already been signed and recorded.
+            printf("CommitTransaction() : Error: Transaction not valid");
+            return false;
+        }
+        wtxNew.RelayWalletTransaction();
+    }
+    MainFrameRepaint();
+    return true;
+}
+
+
+
+
+// requires cs_main lock
+string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
+{
+    CReserveKey reservekey(this);
+    int64 nFeeRequired;
+    if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
+    {
+        string strError;
+        if (nValue + nFeeRequired > GetBalance())
+            strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds  "), FormatMoney(nFeeRequired).c_str());
+        else
+            strError = _("Error: Transaction creation failed  ");
+        printf("SendMoney() : %s", strError.c_str());
+        return strError;
+    }
+
+    if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
+        return "ABORTED";
+
+    if (!CommitTransaction(wtxNew, reservekey))
+        return _("Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
+
+    MainFrameRepaint();
+    return "";
+}
+
+
+
+// requires cs_main lock
+string CWallet::SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
+{
+    // Check amount
+    if (nValue <= 0)
+        return _("Invalid amount");
+    if (nValue + nTransactionFee > GetBalance())
+        return _("Insufficient funds");
+
+    // Parse bitcoin address
+    CScript scriptPubKey;
+    if (!scriptPubKey.SetBitcoinAddress(strAddress))
+        return _("Invalid bitcoin address");
+
+    return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
+}
+
+
+
+
+bool CWallet::LoadWallet(bool& fFirstRunRet)
+{
+    if (!fFileBacked)
+        return false;
+    fFirstRunRet = false;
+    if (!CWalletDB(strWalletFile,"cr+").LoadWallet(this))
+        return false;
+    fFirstRunRet = vchDefaultKey.empty();
+
+    if (!mapKeys.count(vchDefaultKey))
+    {
+        // Create new default key
+        RandAddSeedPerfmon();
+
+        SetDefaultKey(GetKeyFromKeyPool());
+        if (!SetAddressBookName(PubKeyToAddress(vchDefaultKey), ""))
+            return false;
+    }
+
+    CreateThread(ThreadFlushWalletDB, &strWalletFile);
+    return true;
+}
+
+
+bool CWallet::SetAddressBookName(const string& strAddress, const string& strName)
+{
+    mapAddressBook[strAddress] = strName;
+    if (!fFileBacked)
+        return false;
+    return CWalletDB(strWalletFile).WriteName(strAddress, strName);
+}
+
+bool CWallet::DelAddressBookName(const string& strAddress)
+{
+    mapAddressBook.erase(strAddress);
+    if (!fFileBacked)
+        return false;
+    return CWalletDB(strWalletFile).EraseName(strAddress);
+}
+
+
+void CWallet::PrintWallet(const CBlock& block)
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        if (mapWallet.count(block.vtx[0].GetHash()))
+        {
+            CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
+            printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+        }
+    }
+    printf("\n");
+}
+
+bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
+{
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
+        if (mi != mapWallet.end())
+        {
+            wtx = (*mi).second;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
+{
+    if (fFileBacked)
+    {
+        if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
+            return false;
+    }
+    vchDefaultKey = vchPubKey;
+    return true;
+}
+
+bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
+{
+    if (!pwallet->fFileBacked)
+        return false;
+    strWalletFileOut = pwallet->strWalletFile;
+    return true;
+}
+
+void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
+{
+    nIndex = -1;
+    keypool.vchPubKey.clear();
+    CRITICAL_BLOCK(cs_main)
+    CRITICAL_BLOCK(cs_mapWallet)
+    CRITICAL_BLOCK(cs_setKeyPool)
+    {
+        CWalletDB walletdb(strWalletFile);
+
+        // Top up key pool
+        int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
+        while (setKeyPool.size() < nTargetSize+1)
+        {
+            int64 nEnd = 1;
+            if (!setKeyPool.empty())
+                nEnd = *(--setKeyPool.end()) + 1;
+            if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
+                throw runtime_error("ReserveKeyFromKeyPool() : writing generated key failed");
+            setKeyPool.insert(nEnd);
+            printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
+        }
+
+        // Get the oldest key
+        assert(!setKeyPool.empty());
+        nIndex = *(setKeyPool.begin());
+        setKeyPool.erase(setKeyPool.begin());
+        if (!walletdb.ReadPool(nIndex, keypool))
+            throw runtime_error("ReserveKeyFromKeyPool() : read failed");
+        if (!mapKeys.count(keypool.vchPubKey))
+            throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
+        assert(!keypool.vchPubKey.empty());
+        printf("keypool reserve %"PRI64d"\n", nIndex);
+    }
+}
+
+void CWallet::KeepKey(int64 nIndex)
+{
+    // Remove from key pool
+    if (fFileBacked)
+    {
+        CWalletDB walletdb(strWalletFile);
+        CRITICAL_BLOCK(cs_main)
+        {
+            walletdb.ErasePool(nIndex);
+        }
+    }
+    printf("keypool keep %"PRI64d"\n", nIndex);
+}
+
+void CWallet::ReturnKey(int64 nIndex)
+{
+    // Return to key pool
+    CRITICAL_BLOCK(cs_setKeyPool)
+        setKeyPool.insert(nIndex);
+    printf("keypool return %"PRI64d"\n", nIndex);
+}
+
+vector<unsigned char> CWallet::GetKeyFromKeyPool()
+{
+    int64 nIndex = 0;
+    CKeyPool keypool;
+    ReserveKeyFromKeyPool(nIndex, keypool);
+    KeepKey(nIndex);
+    return keypool.vchPubKey;
+}
+
+int64 CWallet::GetOldestKeyPoolTime()
+{
+    int64 nIndex = 0;
+    CKeyPool keypool;
+    ReserveKeyFromKeyPool(nIndex, keypool);
+    ReturnKey(nIndex);
+    return keypool.nTime;
+}
+
+vector<unsigned char> CReserveKey::GetReservedKey()
+{
+    if (nIndex == -1)
+    {
+        CKeyPool keypool;
+        pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
+        vchPubKey = keypool.vchPubKey;
+    }
+    assert(!vchPubKey.empty());
+    return vchPubKey;
+}
+
+void CReserveKey::KeepKey()
+{
+    if (nIndex != -1)
+        pwallet->KeepKey(nIndex);
+    nIndex = -1;
+    vchPubKey.clear();
+}
+
+void CReserveKey::ReturnKey()
+{
+    if (nIndex != -1)
+        pwallet->ReturnKey(nIndex);
+    nIndex = -1;
+    vchPubKey.clear();
+}
+
diff --git a/src/wallet.h b/src/wallet.h
new file mode 100644 (file)
index 0000000..7d9db97
--- /dev/null
@@ -0,0 +1,614 @@
+// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_WALLET_H
+#define BITCOIN_WALLET_H
+
+#include "bignum.h"
+#include "key.h"
+#include "script.h"
+
+class CWalletTx;
+class CReserveKey;
+class CWalletDB;
+
+class CWallet : public CKeyStore
+{
+private:
+    bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
+    bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
+
+
+public:
+    bool fFileBacked;
+    std::string strWalletFile;
+
+    std::set<int64> setKeyPool;
+    CCriticalSection cs_setKeyPool;
+
+    CWallet()
+    {
+        fFileBacked = false;
+    }
+    CWallet(std::string strWalletFileIn)
+    {
+        strWalletFile = strWalletFileIn;
+        fFileBacked = true;
+    }
+
+    mutable CCriticalSection cs_mapWallet;
+    std::map<uint256, CWalletTx> mapWallet;
+    std::vector<uint256> vWalletUpdated;
+
+    std::map<uint256, int> mapRequestCount;
+    mutable CCriticalSection cs_mapRequestCount;
+
+    std::map<std::string, std::string> mapAddressBook;
+    mutable CCriticalSection cs_mapAddressBook;
+
+    std::vector<unsigned char> vchDefaultKey;
+
+    bool AddKey(const CKey& key);
+    bool AddToWallet(const CWalletTx& wtxIn);
+    bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
+    bool EraseFromWallet(uint256 hash);
+    void WalletUpdateSpent(const CTransaction& prevout);
+    int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
+    void ReacceptWalletTransactions();
+    void ResendWalletTransactions();
+    int64 GetBalance() const;
+    bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
+    bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
+    bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
+    bool BroadcastTransaction(CWalletTx& wtxNew);
+    std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
+    std::string SendMoneyToBitcoinAddress(std::string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
+
+    void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
+    void KeepKey(int64 nIndex);
+    void ReturnKey(int64 nIndex);
+    std::vector<unsigned char> GetKeyFromKeyPool();
+    int64 GetOldestKeyPoolTime();
+
+    bool IsMine(const CTxIn& txin) const;
+    int64 GetDebit(const CTxIn& txin) const;
+    bool IsMine(const CTxOut& txout) const
+    {
+        return ::IsMine(*this, txout.scriptPubKey);
+    }
+    int64 GetCredit(const CTxOut& txout) const
+    {
+        if (!MoneyRange(txout.nValue))
+            throw std::runtime_error("CWallet::GetCredit() : value out of range");
+        return (IsMine(txout) ? txout.nValue : 0);
+    }
+    bool IsChange(const CTxOut& txout) const
+    {
+        std::vector<unsigned char> vchPubKey;
+        if (ExtractPubKey(txout.scriptPubKey, this, vchPubKey))
+            CRITICAL_BLOCK(cs_mapAddressBook)
+                if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
+                    return true;
+        return false;
+    }
+    int64 GetChange(const CTxOut& txout) const
+    {
+        if (!MoneyRange(txout.nValue))
+            throw std::runtime_error("CWallet::GetChange() : value out of range");
+        return (IsChange(txout) ? txout.nValue : 0);
+    }
+    bool IsMine(const CTransaction& tx) const
+    {
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+            if (IsMine(txout))
+                return true;
+        return false;
+    }
+    bool IsFromMe(const CTransaction& tx) const
+    {
+        return (GetDebit(tx) > 0);
+    }
+    int64 GetDebit(const CTransaction& tx) const
+    {
+        int64 nDebit = 0;
+        BOOST_FOREACH(const CTxIn& txin, tx.vin)
+        {
+            nDebit += GetDebit(txin);
+            if (!MoneyRange(nDebit))
+                throw std::runtime_error("CWallet::GetDebit() : value out of range");
+        }
+        return nDebit;
+    }
+    int64 GetCredit(const CTransaction& tx) const
+    {
+        int64 nCredit = 0;
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+        {
+            nCredit += GetCredit(txout);
+            if (!MoneyRange(nCredit))
+                throw std::runtime_error("CWallet::GetCredit() : value out of range");
+        }
+        return nCredit;
+    }
+    int64 GetChange(const CTransaction& tx) const
+    {
+        int64 nChange = 0;
+        BOOST_FOREACH(const CTxOut& txout, tx.vout)
+        {
+            nChange += GetChange(txout);
+            if (!MoneyRange(nChange))
+                throw std::runtime_error("CWallet::GetChange() : value out of range");
+        }
+        return nChange;
+    }
+    void SetBestChain(const CBlockLocator& loc)
+    {
+        CWalletDB walletdb(strWalletFile);
+        walletdb.WriteBestBlock(loc);
+    }
+
+    bool LoadWallet(bool& fFirstRunRet);
+//    bool BackupWallet(const std::string& strDest);
+
+    // requires cs_mapAddressBook lock
+    bool SetAddressBookName(const std::string& strAddress, const std::string& strName);
+
+    // requires cs_mapAddressBook lock
+    bool DelAddressBookName(const std::string& strAddress);
+
+    void UpdatedTransaction(const uint256 &hashTx)
+    {
+        CRITICAL_BLOCK(cs_mapWallet)
+            vWalletUpdated.push_back(hashTx);
+    }
+
+    void PrintWallet(const CBlock& block);
+
+    void Inventory(const uint256 &hash)
+    {
+        CRITICAL_BLOCK(cs_mapRequestCount)
+        {
+            std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
+            if (mi != mapRequestCount.end())
+                (*mi).second++;
+        }
+    }
+
+    bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
+
+    bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
+};
+
+
+class CReserveKey
+{
+protected:
+    CWallet* pwallet;
+    int64 nIndex;
+    std::vector<unsigned char> vchPubKey;
+public:
+    CReserveKey(CWallet* pwalletIn)
+    {
+        nIndex = -1;
+        pwallet = pwalletIn;
+    }
+
+    ~CReserveKey()
+    {
+        if (!fShutdown)
+            ReturnKey();
+    }
+
+    void ReturnKey();
+    std::vector<unsigned char> GetReservedKey();
+    void KeepKey();
+};
+
+
+//
+// A transaction with a bunch of additional info that only the owner cares
+// about.  It includes any unrecorded transactions needed to link it back
+// to the block chain.
+//
+class CWalletTx : public CMerkleTx
+{
+public:
+    const CWallet* pwallet;
+
+    std::vector<CMerkleTx> vtxPrev;
+    std::map<std::string, std::string> mapValue;
+    std::vector<std::pair<std::string, std::string> > vOrderForm;
+    unsigned int fTimeReceivedIsTxTime;
+    unsigned int nTimeReceived;  // time received by this node
+    char fFromMe;
+    std::string strFromAccount;
+    std::vector<char> vfSpent;
+
+    // memory only
+    mutable char fDebitCached;
+    mutable char fCreditCached;
+    mutable char fAvailableCreditCached;
+    mutable char fChangeCached;
+    mutable int64 nDebitCached;
+    mutable int64 nCreditCached;
+    mutable int64 nAvailableCreditCached;
+    mutable int64 nChangeCached;
+
+    // memory only UI hints
+    mutable unsigned int nTimeDisplayed;
+    mutable int nLinesDisplayed;
+    mutable char fConfirmedDisplayed;
+
+    CWalletTx()
+    {
+        Init(NULL);
+    }
+
+    CWalletTx(const CWallet* pwalletIn)
+    {
+        Init(pwalletIn);
+    }
+
+    CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
+    {
+        Init(pwalletIn);
+    }
+
+    CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
+    {
+        Init(pwalletIn);
+    }
+
+    void Init(const CWallet* pwalletIn)
+    {
+        pwallet = pwalletIn;
+        vtxPrev.clear();
+        mapValue.clear();
+        vOrderForm.clear();
+        fTimeReceivedIsTxTime = false;
+        nTimeReceived = 0;
+        fFromMe = false;
+        strFromAccount.clear();
+        vfSpent.clear();
+        fDebitCached = false;
+        fCreditCached = false;
+        fAvailableCreditCached = false;
+        fChangeCached = false;
+        nDebitCached = 0;
+        nCreditCached = 0;
+        nAvailableCreditCached = 0;
+        nChangeCached = 0;
+        nTimeDisplayed = 0;
+        nLinesDisplayed = 0;
+        fConfirmedDisplayed = false;
+    }
+
+    IMPLEMENT_SERIALIZE
+    (
+        CWalletTx* pthis = const_cast<CWalletTx*>(this);
+        if (fRead)
+            pthis->Init(NULL);
+        char fSpent = false;
+
+        if (!fRead)
+        {
+            pthis->mapValue["fromaccount"] = pthis->strFromAccount;
+
+            std::string str;
+            BOOST_FOREACH(char f, vfSpent)
+            {
+                str += (f ? '1' : '0');
+                if (f)
+                    fSpent = true;
+            }
+            pthis->mapValue["spent"] = str;
+        }
+
+        nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
+        READWRITE(vtxPrev);
+        READWRITE(mapValue);
+        READWRITE(vOrderForm);
+        READWRITE(fTimeReceivedIsTxTime);
+        READWRITE(nTimeReceived);
+        READWRITE(fFromMe);
+        READWRITE(fSpent);
+
+        if (fRead)
+        {
+            pthis->strFromAccount = pthis->mapValue["fromaccount"];
+
+            if (mapValue.count("spent"))
+                BOOST_FOREACH(char c, pthis->mapValue["spent"])
+                    pthis->vfSpent.push_back(c != '0');
+            else
+                pthis->vfSpent.assign(vout.size(), fSpent);
+        }
+
+        pthis->mapValue.erase("fromaccount");
+        pthis->mapValue.erase("version");
+        pthis->mapValue.erase("spent");
+    )
+
+    // marks certain txout's as spent
+    // returns true if any update took place
+    bool UpdateSpent(const std::vector<char>& vfNewSpent)
+    {
+        bool fReturn = false;
+        for (int i=0; i < vfNewSpent.size(); i++)
+        {
+            if (i == vfSpent.size())
+                break;
+
+            if (vfNewSpent[i] && !vfSpent[i])
+            {
+                vfSpent[i] = true;
+                fReturn = true;
+                fAvailableCreditCached = false;
+            }
+        }
+        return fReturn;
+    }
+
+    void MarkDirty()
+    {
+        fCreditCached = false;
+        fAvailableCreditCached = false;
+        fDebitCached = false;
+        fChangeCached = false;
+    }
+
+    void MarkSpent(unsigned int nOut)
+    {
+        if (nOut >= vout.size())
+            throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
+        vfSpent.resize(vout.size());
+        if (!vfSpent[nOut])
+        {
+            vfSpent[nOut] = true;
+            fAvailableCreditCached = false;
+        }
+    }
+
+    bool IsSpent(unsigned int nOut) const
+    {
+        if (nOut >= vout.size())
+            throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
+        if (nOut >= vfSpent.size())
+            return false;
+        return (!!vfSpent[nOut]);
+    }
+
+    int64 GetDebit() const
+    {
+        if (vin.empty())
+            return 0;
+        if (fDebitCached)
+            return nDebitCached;
+        nDebitCached = pwallet->GetDebit(*this);
+        fDebitCached = true;
+        return nDebitCached;
+    }
+
+    int64 GetCredit(bool fUseCache=true) const
+    {
+        // Must wait until coinbase is safely deep enough in the chain before valuing it
+        if (IsCoinBase() && GetBlocksToMaturity() > 0)
+            return 0;
+
+        // GetBalance can assume transactions in mapWallet won't change
+        if (fUseCache && fCreditCached)
+            return nCreditCached;
+        nCreditCached = pwallet->GetCredit(*this);
+        fCreditCached = true;
+        return nCreditCached;
+    }
+
+    int64 GetAvailableCredit(bool fUseCache=true) const
+    {
+        // Must wait until coinbase is safely deep enough in the chain before valuing it
+        if (IsCoinBase() && GetBlocksToMaturity() > 0)
+            return 0;
+
+        if (fUseCache && fAvailableCreditCached)
+            return nAvailableCreditCached;
+
+        int64 nCredit = 0;
+        for (int i = 0; i < vout.size(); i++)
+        {
+            if (!IsSpent(i))
+            {
+                const CTxOut &txout = vout[i];
+                nCredit += pwallet->GetCredit(txout);
+                if (!MoneyRange(nCredit))
+                    throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+            }
+        }
+
+        nAvailableCreditCached = nCredit;
+        fAvailableCreditCached = true;
+        return nCredit;
+    }
+
+
+    int64 GetChange() const
+    {
+        if (fChangeCached)
+            return nChangeCached;
+        nChangeCached = pwallet->GetChange(*this);
+        fChangeCached = true;
+        return nChangeCached;
+    }
+
+    void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<std::string /* address */, int64> >& listReceived,
+                    std::list<std::pair<std::string /* address */, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
+
+    void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, 
+                           int64& nSent, int64& nFee) const;
+
+    bool IsFromMe() const
+    {
+        return (GetDebit() > 0);
+    }
+
+    bool IsConfirmed() const
+    {
+        // Quick answer in most cases
+        if (!IsFinal())
+            return false;
+        if (GetDepthInMainChain() >= 1)
+            return true;
+        if (!IsFromMe()) // using wtx's cached debit
+            return false;
+
+        // If no confirmations but it's from us, we can still
+        // consider it confirmed if all dependencies are confirmed
+        std::map<uint256, const CMerkleTx*> mapPrev;
+        std::vector<const CMerkleTx*> vWorkQueue;
+        vWorkQueue.reserve(vtxPrev.size()+1);
+        vWorkQueue.push_back(this);
+        for (int i = 0; i < vWorkQueue.size(); i++)
+        {
+            const CMerkleTx* ptx = vWorkQueue[i];
+
+            if (!ptx->IsFinal())
+                return false;
+            if (ptx->GetDepthInMainChain() >= 1)
+                continue;
+            if (!pwallet->IsFromMe(*ptx))
+                return false;
+
+            if (mapPrev.empty())
+                BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
+                    mapPrev[tx.GetHash()] = &tx;
+
+            BOOST_FOREACH(const CTxIn& txin, ptx->vin)
+            {
+                if (!mapPrev.count(txin.prevout.hash))
+                    return false;
+                vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
+            }
+        }
+        return true;
+    }
+
+    bool WriteToDisk();
+
+    int64 GetTxTime() const;
+    int GetRequestCount() const;
+
+    void AddSupportingTransactions(CTxDB& txdb);
+
+    bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
+    bool AcceptWalletTransaction();
+
+    void RelayWalletTransaction(CTxDB& txdb);
+    void RelayWalletTransaction();
+};
+
+
+//
+// Private key that includes an expiration date in case it never gets used.
+//
+class CWalletKey
+{
+public:
+    CPrivKey vchPrivKey;
+    int64 nTimeCreated;
+    int64 nTimeExpires;
+    std::string strComment;
+    //// todo: add something to note what created it (user, getnewaddress, change)
+    ////   maybe should have a map<string, string> property map
+
+    CWalletKey(int64 nExpires=0)
+    {
+        nTimeCreated = (nExpires ? GetTime() : 0);
+        nTimeExpires = nExpires;
+    }
+
+    IMPLEMENT_SERIALIZE
+    (
+        if (!(nType & SER_GETHASH))
+            READWRITE(nVersion);
+        READWRITE(vchPrivKey);
+        READWRITE(nTimeCreated);
+        READWRITE(nTimeExpires);
+        READWRITE(strComment);
+    )
+};
+
+
+
+
+
+
+//
+// Account information.
+// Stored in wallet with key "acc"+string account name
+//
+class CAccount
+{
+public:
+    std::vector<unsigned char> vchPubKey;
+
+    CAccount()
+    {
+        SetNull();
+    }
+
+    void SetNull()
+    {
+        vchPubKey.clear();
+    }
+
+    IMPLEMENT_SERIALIZE
+    (
+        if (!(nType & SER_GETHASH))
+            READWRITE(nVersion);
+        READWRITE(vchPubKey);
+    )
+};
+
+
+
+//
+// Internal transfers.
+// Database key is acentry<account><counter>
+//
+class CAccountingEntry
+{
+public:
+    std::string strAccount;
+    int64 nCreditDebit;
+    int64 nTime;
+    std::string strOtherAccount;
+    std::string strComment;
+
+    CAccountingEntry()
+    {
+        SetNull();
+    }
+
+    void SetNull()
+    {
+        nCreditDebit = 0;
+        nTime = 0;
+        strAccount.clear();
+        strOtherAccount.clear();
+        strComment.clear();
+    }
+
+    IMPLEMENT_SERIALIZE
+    (
+        if (!(nType & SER_GETHASH))
+            READWRITE(nVersion);
+        // Note: strAccount is serialized as part of the key, not here.
+        READWRITE(nCreditDebit);
+        READWRITE(nTime);
+        READWRITE(strOtherAccount);
+        READWRITE(strComment);
+    )
+};
+
+bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
+
+#endif