Browse Source

Merge branch 'master' of https://github.com/bitcoin/bitcoin

Conflicts:
	src/main.cpp
miguelfreitas
Wladimir J. van der Laan 13 years ago
parent
commit
7a15d4ff67
  1. 38
      contrib/boost-win32.yml
  2. 77
      contrib/gitian-win32.yml
  3. 36
      contrib/gitian.yml
  4. 6
      contrib/pyminer/README
  5. 32
      contrib/pyminer/example-config.cfg
  6. 252
      contrib/pyminer/pyminer.py
  7. 4
      contrib/wx-patches/README
  8. 86
      contrib/wx-patches/toplevel.cpp.diff
  9. 9
      contrib/wx-patches/toplevel.h.diff
  10. 40
      contrib/wxwidgets-win32.yml
  11. 42
      contrib/wxwidgets.yml
  12. 48
      doc/README
  13. 36
      doc/build-msw.txt
  14. 18
      doc/build-osx.txt
  15. 21
      doc/build-unix.txt
  16. 44
      doc/coding.txt
  17. 636
      locale/pl/LC_MESSAGES/bitcoin.po
  18. 642
      src/bitcoinrpc.cpp
  19. 3
      src/db.cpp
  20. 21
      src/keystore.cpp
  21. 54
      src/keystore.h
  22. 24
      src/main.cpp
  23. 14
      src/main.h
  24. 60
      src/makefile.linux-mingw
  25. 67
      src/makefile.mingw
  26. 39
      src/makefile.osx
  27. 39
      src/makefile.unix
  28. 50
      src/makefile.vc
  29. 128
      src/net.cpp
  30. 405
      src/net.h
  31. 312
      src/protocol.cpp
  32. 150
      src/protocol.h
  33. 102
      src/script.cpp
  34. 11
      src/serialize.h
  35. 381
      src/ui.cpp
  36. 8
      src/util.cpp
  37. 8
      src/util.h
  38. 239
      src/wallet.cpp
  39. 17
      src/wallet.h

38
contrib/boost-win32.yml

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
---
name: "boost"
suites:
- "lucid"
architectures:
- "i386"
packages:
- "mingw32"
- "faketime"
- "zip"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
- "boost_1_47_0.tar.bz2"
script: |
TMPDIR="$HOME/tmpdir"
mkdir -p $TMPDIR/bin/$GBUILD_BITS $TMPDIR/include
tar xjf boost_1_47_0.tar.bz2
cd boost_1_47_0
echo "using gcc : 4.4 : i586-mingw32msvc-g++
:
<rc>i586-mingw32msvc-windres
<archiver>i586-mingw32msvc-ar
<cxxflags>-frandom-seed=boost1
;" > user-config.jam
./bootstrap.sh --without-icu
./bjam toolset=gcc target-os=windows threadapi=win32 threading=multi variant=release link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete $MAKEOPTS stage
for lib in chrono date_time exception filesystem graph iostreams math_c99f math_c99l math_c99 math_tr1f math_tr1l math_tr1 prg_exec_monitor program_options random regex serialization signals system test_exec_monitor thread_win32 unit_test_framework wave wserialization; do
mkdir $lib
(cd $lib ; ar xf ../stage/lib/libboost_${lib}-mt-s.a)
mv $lib $TMPDIR/bin/$GBUILD_BITS
done
cp -a boost $TMPDIR/include
cd $TMPDIR
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
zip -r boost-win32-1.47.0-gitian.zip *
cp boost-win32-1.47.0-gitian.zip $OUTDIR

77
contrib/gitian-win32.yml

@ -9,25 +9,44 @@ packages: @@ -9,25 +9,44 @@ packages:
- "git-core"
- "unzip"
- "nsis"
- "faketime"
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"
- "wxwidgets-win32-2.9.2-gitian.zip"
- "boost-win32-1.47.0-gitian.zip"
- "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"
- "db-4.8.30.NC.tar.gz"
- "miniupnpc-1.6.tar.gz"
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
mkdir wxWidgets-2.9.2
cd wxWidgets-2.9.2
mkdir lib
unzip ../wxwidgets-win32-2.9.2-gitian.zip
cd bin/$GBUILD_BITS
for lib in wx_mswu; do
i586-mingw32msvc-ar rc ../../lib/lib${lib}-2.9-i586-mingw32msvc.a $lib/*.o
i586-mingw32msvc-ranlib ../../lib/lib${lib}-2.9-i586-mingw32msvc.a
done
cp -a wx ../../lib
cd ../..
mv include/wx-2.9/wx include
cd ..
#
mkdir boost_1_47_0
cd boost_1_47_0
mkdir -p stage/lib
unzip ../boost-win32-1.47.0-gitian.zip
cd bin/$GBUILD_BITS
for lib in *; do
i586-mingw32msvc-ar rc ../../stage/lib/libboost_${lib}-mt-s.a $lib/*.o
i586-mingw32msvc-ranlib ../../stage/lib/libboost_${lib}-mt-s.a
done
cd ../..
mv include/boost .
cd ..
#
tar xzf openssl-1.0.0d.tar.gz
@ -36,33 +55,19 @@ script: | @@ -36,33 +55,19 @@ script: |
make
cd ..
#
tar xzf db-4.7.25.NC.tar.gz
cd db-4.7.25.NC/build_unix
tar xzf db-4.8.30.NC.tar.gz
cd db-4.8.30.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
tar xzf miniupnpc-1.6.tar.gz
cd miniupnpc-1.6
sed 's/dllwrap -k --driver-name gcc/$(DLLWRAP) -k --driver-name $(CC)/' -i Makefile.mingw
sed 's|wingenminiupnpcstrings $< $@|./wingenminiupnpcstrings $< $@|' -i Makefile.mingw
make -f Makefile.mingw DLLWRAP=i586-mingw32msvc-dllwrap CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar
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
mv miniupnpc-1.6 miniupnpc
#
cd bitcoin
mkdir -p $OUTDIR/src
@ -72,8 +77,10 @@ script: | @@ -72,8 +77,10 @@ script: |
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
sed 's/$(DEBUGFLAGS)/-frandom-seed=bitcoin/' -i makefile.linux-mingw
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
export TZ=UTC
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

36
contrib/gitian.yml

@ -6,40 +6,40 @@ architectures: @@ -6,40 +6,40 @@ architectures:
- "i386"
- "amd64"
packages:
- "libdb4.7++-dev"
- "libdb4.8++-dev"
- "libxxf86vm-dev"
- "libgtk2.0-dev"
- "libboost-all-dev"
- "libssl-dev"
- "git-core"
- "unzip"
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"
- "miniupnpc-1.5.tar.gz"
- "toplevel.h.diff"
- "toplevel.cpp.diff"
- "wxWidgets-2.9.2-gitian.zip"
- "miniupnpc-1.6.tar.gz"
script: |
INSTDIR="$HOME/install"
export LIBRARY_PATH="$INSTDIR/lib"
#
tar xzf miniupnpc-1.5.tar.gz
cd miniupnpc-1.5
tar xzf miniupnpc-1.6.tar.gz
cd miniupnpc-1.6
INSTALLPREFIX=$INSTDIR make $MAKEOPTS install
cd ..
#
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
mkdir -p $INSTDIR/bin $INSTDIR/lib/wx $INSTDIR/include
mkdir wxWidgets-2.9.2
cd wxWidgets-2.9.2
unzip ../wxWidgets-2.9.2-gitian.zip
cp -a bin/$GBUILD_BITS/wx/config/gtk2-unicode-static-2.9 $INSTDIR/bin/wx-config
for lib in wx_gtk2u wxregexu wxtiff; do
ar rc $INSTDIR/lib/lib${lib}-2.9.a bin/$GBUILD_BITS/$lib/*.o
ranlib $INSTDIR/lib/lib${lib}-2.9.a
done
cp -a include/wx-2.9/* $INSTDIR/include
cp -a bin/$GBUILD_BITS/wx/include $INSTDIR/lib/wx
cd ..
#
cd bitcoin
@ -50,7 +50,7 @@ script: | @@ -50,7 +50,7 @@ script: |
cp $OUTDIR/src/doc/README $OUTDIR
cp $OUTDIR/src/COPYING $OUTDIR
cd src
sed 's/$(DEBUGFLAGS)//' < makefile.unix > makefile.unix.2 && mv makefile.unix.2 makefile.unix
sed 's/$(DEBUGFLAGS)//' -i 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

6
contrib/pyminer/README

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
This is a 'getwork' CPU mining client for bitcoin.
It is pure-python, and therefore very, very slow. The purpose is to
provide a reference implementation of a miner, for study.

32
contrib/pyminer/example-config.cfg

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
#
# RPC login details
#
host=127.0.0.1
port=8332
rpcuser=myusername
rpcpass=mypass
#
# mining details
#
threads=4
# periodic rate for requesting new work, if solution not found
scantime=60
#
# misc.
#
# not really used right now
logdir=/tmp/pyminer
# set to 1, to enable hashmeter output
hashmeter=0

252
contrib/pyminer/pyminer.py

@ -0,0 +1,252 @@ @@ -0,0 +1,252 @@
#!/usr/bin/python
#
# Copyright (c) 2011 The Bitcoin developers
# Distributed under the MIT/X11 software license, see the accompanying
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
#
import time
import json
import pprint
import hashlib
import struct
import re
import base64
import httplib
import sys
from multiprocessing import Process
ERR_SLEEP = 15
MAX_NONCE = 1000000L
settings = {}
pp = pprint.PrettyPrinter(indent=4)
class BitcoinRPC:
OBJID = 1
def __init__(self, host, port, username, password):
authpair = "%s:%s" % (username, password)
self.authhdr = "Basic %s" % (base64.b64encode(authpair))
self.conn = httplib.HTTPConnection(host, port, False, 30)
def rpc(self, method, params=None):
self.OBJID += 1
obj = { 'version' : '1.1',
'method' : method,
'id' : self.OBJID }
if params is None:
obj['params'] = []
else:
obj['params'] = params
self.conn.request('POST', '/', json.dumps(obj),
{ 'Authorization' : self.authhdr,
'Content-type' : 'application/json' })
resp = self.conn.getresponse()
if resp is None:
print "JSON-RPC: no response"
return None
body = resp.read()
resp_obj = json.loads(body)
if resp_obj is None:
print "JSON-RPC: cannot JSON-decode body"
return None
if 'error' in resp_obj and resp_obj['error'] != None:
return resp_obj['error']
if 'result' not in resp_obj:
print "JSON-RPC: no result in object"
return None
return resp_obj['result']
def getblockcount(self):
return self.rpc('getblockcount')
def getwork(self, data=None):
return self.rpc('getwork', data)
def uint32(x):
return x & 0xffffffffL
def bytereverse(x):
return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) |
(((x) >> 8) & 0x0000ff00) | ((x) >> 24) ))
def bufreverse(in_buf):
out_words = []
for i in range(0, len(in_buf), 4):
word = struct.unpack('@I', in_buf[i:i+4])[0]
out_words.append(struct.pack('@I', bytereverse(word)))
return ''.join(out_words)
def wordreverse(in_buf):
out_words = []
for i in range(0, len(in_buf), 4):
out_words.append(in_buf[i:i+4])
out_words.reverse()
return ''.join(out_words)
class Miner:
def __init__(self, id):
self.id = id
self.max_nonce = MAX_NONCE
def work(self, datastr, targetstr):
# decode work data hex string to binary
static_data = datastr.decode('hex')
static_data = bufreverse(static_data)
# the first 76b of 80b do not change
blk_hdr = static_data[:76]
# decode 256-bit target value
targetbin = targetstr.decode('hex')
targetbin = targetbin[::-1] # byte-swap and dword-swap
targetbin_str = targetbin.encode('hex')
target = long(targetbin_str, 16)
# pre-hash first 76b of block header
static_hash = hashlib.sha256()
static_hash.update(blk_hdr)
for nonce in xrange(self.max_nonce):
# encode 32-bit nonce value
nonce_bin = struct.pack("<I", nonce)
# hash final 4b, the nonce value
hash1_o = static_hash.copy()
hash1_o.update(nonce_bin)
hash1 = hash1_o.digest()
# sha256 hash of sha256 hash
hash_o = hashlib.sha256()
hash_o.update(hash1)
hash = hash_o.digest()
# quick test for winning solution: high 32 bits zero?
if hash[-4:] != '\0\0\0\0':
continue
# convert binary hash to 256-bit Python long
hash = bufreverse(hash)
hash = wordreverse(hash)
hash_str = hash.encode('hex')
l = long(hash_str, 16)
# proof-of-work test: hash < target
if l < target:
print time.asctime(), "PROOF-OF-WORK found: %064x" % (l,)
return (nonce + 1, nonce_bin)
else:
print time.asctime(), "PROOF-OF-WORK false positive %064x" % (l,)
# return (nonce + 1, nonce_bin)
return (nonce + 1, None)
def submit_work(self, rpc, original_data, nonce_bin):
nonce_bin = bufreverse(nonce_bin)
nonce = nonce_bin.encode('hex')
solution = original_data[:152] + nonce + original_data[160:256]
param_arr = [ solution ]
result = rpc.getwork(param_arr)
print time.asctime(), "--> Upstream RPC result:", result
def iterate(self, rpc):
work = rpc.getwork()
if work is None:
time.sleep(ERR_SLEEP)
return
if 'data' not in work or 'target' not in work:
time.sleep(ERR_SLEEP)
return
time_start = time.time()
(hashes_done, nonce_bin) = self.work(work['data'],
work['target'])
time_end = time.time()
time_diff = time_end - time_start
self.max_nonce = long(
(hashes_done * settings['scantime']) / time_diff)
if self.max_nonce > 0xfffffffaL:
self.max_nonce = 0xfffffffaL
if settings['hashmeter']:
print "HashMeter(%d): %d hashes, %.2f Khash/sec" % (
self.id, hashes_done,
(hashes_done / 1000.0) / time_diff)
if nonce_bin is not None:
self.submit_work(rpc, work['data'], nonce_bin)
def loop(self):
rpc = BitcoinRPC(settings['host'], settings['port'],
settings['rpcuser'], settings['rpcpass'])
if rpc is None:
return
while True:
self.iterate(rpc)
def miner_thread(id):
miner = Miner(id)
miner.loop()
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: pyminer.py CONFIG-FILE"
sys.exit(1)
f = open(sys.argv[1])
for line in f:
# skip comment lines
m = re.search('^\s*#', line)
if m:
continue
# parse key=value lines
m = re.search('^(\w+)\s*=\s*(\S.*)$', line)
if m is None:
continue
settings[m.group(1)] = m.group(2)
f.close()
if 'host' not in settings:
settings['host'] = '127.0.0.1'
if 'port' not in settings:
settings['port'] = 8332
if 'threads' not in settings:
settings['threads'] = 1
if 'hashmeter' not in settings:
settings['hashmeter'] = 0
if 'scantime' not in settings:
settings['scantime'] = 30L
if 'rpcuser' not in settings or 'rpcpass' not in settings:
print "Missing username and/or password in cfg file"
sys.exit(1)
settings['port'] = int(settings['port'])
settings['threads'] = int(settings['threads'])
settings['hashmeter'] = int(settings['hashmeter'])
settings['scantime'] = long(settings['scantime'])
thr_list = []
for thr_id in range(settings['threads']):
p = Process(target=miner_thread, args=(thr_id,))
p.start()
thr_list.append(p)
time.sleep(1) # stagger threads
print settings['threads'], "mining threads started"
print time.asctime(), "Miner Starts - %s:%s" % (settings['host'], settings['port'])
try:
for thr_proc in thr_list:
thr_proc.join()
except KeyboardInterrupt:
pass
print time.asctime(), "Miner Stops - %s:%s" % (settings['host'], settings['port'])

4
contrib/wx-patches/README

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
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.

86
contrib/wx-patches/toplevel.cpp.diff

@ -1,86 +0,0 @@ @@ -1,86 +0,0 @@
--- /wxWidgets/trunk/src/gtk/toplevel.cpp (revision 67326)
+++ /wxWidgets/trunk/src/gtk/toplevel.cpp (revision 67496)
@@ -72,4 +72,8 @@
// send any activate events at all
static int g_sendActivateEvent = -1;
+
+// Whether _NET_REQUEST_FRAME_EXTENTS support is working
+// 0 == not tested yet, 1 == working, 2 == broken
+static int gs_requestFrameExtentsStatus;
//-----------------------------------------------------------------------------
@@ -432,4 +436,12 @@
if (event->state == GDK_PROPERTY_NEW_VALUE && event->atom == property)
{
+ if (win->m_netFrameExtentsTimerId)
+ {
+ // WM support for _NET_REQUEST_FRAME_EXTENTS is working
+ gs_requestFrameExtentsStatus = 1;
+ g_source_remove(win->m_netFrameExtentsTimerId);
+ win->m_netFrameExtentsTimerId = 0;
+ }
+
wxSize decorSize = win->m_decorSize;
int left, right, top, bottom;
@@ -439,4 +451,22 @@
win->GTKUpdateDecorSize(decorSize);
}
+ return false;
+}
+}
+
+extern "C" {
+static gboolean request_frame_extents_timeout(void* data)
+{
+ // WM support for _NET_REQUEST_FRAME_EXTENTS is broken
+ gs_requestFrameExtentsStatus = 2;
+ gdk_threads_enter();
+ wxTopLevelWindowGTK* win = static_cast<wxTopLevelWindowGTK*>(data);
+ win->m_netFrameExtentsTimerId = 0;
+ wxSize decorSize = win->m_decorSize;
+ int left, right, top, bottom;
+ if (wxGetFrameExtents(gtk_widget_get_window(win->m_widget), &left, &right, &top, &bottom))
+ decorSize.Set(left + right, top + bottom);
+ win->GTKUpdateDecorSize(decorSize);
+ gdk_threads_leave();
return false;
}
@@ -459,4 +489,5 @@
m_deferShowAllowed = true;
m_updateDecorSize = true;
+ m_netFrameExtentsTimerId = 0;
m_urgency_hint = -2;
@@ -811,5 +842,6 @@
if (deferShow)
{
- deferShow = m_deferShowAllowed && !GTK_WIDGET_REALIZED(m_widget);
+ deferShow = gs_requestFrameExtentsStatus != 2 &&
+ m_deferShowAllowed && !gtk_widget_get_realized(m_widget);
if (deferShow)
{
@@ -829,11 +861,4 @@
// GetSize()/SetSize() because it makes window bigger between each
// restore and save.
- m_updateDecorSize = deferShow;
- }
- if (deferShow)
- {
- // Fluxbox support for _NET_REQUEST_FRAME_EXTENTS is broken
- const char* name = gdk_x11_screen_get_window_manager_name(screen);
- deferShow = strcmp(name, "Fluxbox") != 0;
m_updateDecorSize = deferShow;
}
@@ -875,4 +900,12 @@
(XEvent*)&xevent);
+ if (gs_requestFrameExtentsStatus == 0)
+ {
+ // if WM does not respond to request within 1 second,
+ // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working
+ m_netFrameExtentsTimerId =
+ g_timeout_add(1000, request_frame_extents_timeout, this);
+ }
+
// defer calling gtk_widget_show()
m_isShown = true;

9
contrib/wx-patches/toplevel.h.diff

@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
--- /wxWidgets/trunk/include/wx/gtk/toplevel.h (revision 65373)
+++ /wxWidgets/trunk/include/wx/gtk/toplevel.h (revision 67496)
@@ -114,4 +114,6 @@
// wxUSER_ATTENTION_ERROR difference, -2 for no hint, -1 for ERROR hint, rest for GtkTimeout handle.
int m_urgency_hint;
+ // timer for detecting WM with broken _NET_REQUEST_FRAME_EXTENTS handling
+ unsigned m_netFrameExtentsTimerId;
// return the size of the window without WM decorations

40
contrib/wxwidgets-win32.yml

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
---
name: "wxwidgets"
suites:
- "lucid"
architectures:
- "i386"
packages:
- "mingw32"
- "faketime"
- "zip"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
- "wxWidgets-2.9.2.tar.bz2"
script: |
INSTDIR="$HOME/install"
TMPDIR="$HOME/tmpdir"
export LIBRARY_PATH="$INSTDIR/lib"
#
tar xjf wxWidgets-2.9.2.tar.bz2
cd wxWidgets-2.9.2
CXXFLAGS=-frandom-seed=wx1 ./configure --host=i586-mingw32msvc --build=i686-linux --prefix=$INSTDIR --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 install
mkdir $TMPDIR
cd $TMPDIR
cp -af $INSTDIR/include .
mkdir -p $TMPDIR/bin/$GBUILD_BITS
cd $TMPDIR/bin/$GBUILD_BITS
cp -af $INSTDIR/lib/wx .
for lib in wx_mswu; do
mkdir $lib
(cd $lib ; ar xf $INSTDIR/lib/lib${lib}-2.9-i586-mingw32msvc.a)
done
chmod -R +w $TMPDIR
cd $TMPDIR
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
zip -r wxwidgets-win32-2.9.2-gitian.zip *
cp wxwidgets-win32-2.9.2-gitian.zip $OUTDIR

42
contrib/wxwidgets.yml

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
---
name: "wxwidgets"
suites:
- "lucid"
architectures:
- "i386"
- "amd64"
packages:
- "libxxf86vm-dev"
- "libgtk2.0-dev"
- "faketime"
- "zip"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
- "wxWidgets-2.9.2.tar.bz2"
script: |
INSTDIR="$HOME/install"
TMPDIR="$HOME/tmpdir"
export LIBRARY_PATH="$INSTDIR/lib"
#
tar xjf wxWidgets-2.9.2.tar.bz2
cd wxWidgets-2.9.2
./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
mkdir $TMPDIR
cd $TMPDIR
cp -af $INSTDIR/include .
mkdir -p $TMPDIR/bin/$GBUILD_BITS
cd $TMPDIR/bin/$GBUILD_BITS
cp -af $INSTDIR/lib/wx .
for lib in wxtiff wxregexu wx_gtk2u; do
mkdir $lib
(cd $lib ; ar xf $INSTDIR/lib/lib${lib}-2.9.a)
done
chmod -R +w $TMPDIR
cd $TMPDIR
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
export FAKETIME=$REFERENCE_DATETIME
zip -r wxWidgets-2.9.2-gitian.zip *
cp wxWidgets-2.9.2-gitian.zip $OUTDIR

48
doc/README

@ -36,7 +36,7 @@ every time you wish to send Bitcoins. If you lose this passphrase, @@ -36,7 +36,7 @@ every time you wish to send Bitcoins. If you lose this passphrase,
you will lose access to spend all of the bitcoins in your wallet,
no one, not even the Bitcoin developers can recover your Bitcoins.
This means you are responsible for your own security, store your
password in a secure location and do not forget it.
passphrase in a secure location and do not forget it.
Remember that the encryption built into bitcoin only encrypts the
actual keys which are required to send your bitcoins, not the full
@ -57,7 +57,7 @@ If everything goes fine, delete the backup and enjoy your encrypted @@ -57,7 +57,7 @@ If everything goes fine, delete the backup and enjoy your encrypted
wallet. Note that once you encrypt your wallet, you will never be
able to go back to a version of the Bitcoin client older than 0.4.
Keep in mind that you are always responsible for you own security.
Keep in mind that you are always responsible for your own security.
All it takes is a slightly more advanced wallet-stealing trojan which
installs a keylogger to steal your wallet passphrase as you enter it
in addition to your wallet file and you have lost all your Bitcoins.
@ -67,6 +67,50 @@ entering your wallet passphrase in the Bitcoin client and using the @@ -67,6 +67,50 @@ entering your wallet passphrase in the Bitcoin client and using the
same passphrase only as your wallet passphrase.
Technical details of wallet encryption
--------------------------------------
Wallet encryption uses AES-256-CBC to encrypt only the private keys
that are held in a wallet. The keys are encrypted with a master key
which is entirely random. This master key is then encrypted with
AES-256-CBC with a key derived from the passphrase using SHA512 and
OpenSSL's EVP_BytesToKey and a dynamic number of rounds determined by
the speed of the machine which does the initial encryption (and is
updated based on the speed of a computer which does a subsequent
passphrase change). Although the underlying code supports multiple
encrypted copies of the same master key (and thus multiple passphrases)
the client does not yet have a method to add additional passphrases.
At runtime, the client loads the wallet as it normally would, however
the keystore stores the keys in encrypted form. When the passphrase
is required (to top up keypool or send coins) it will either be queried
by a GUI prompt, or must first be entered with the walletpassphrase
RPC command. This will change the wallet to "unlocked" state where the
unencrypted master key is stored in memory (in the case of GUI, only for
long enough to complete the requested operation, in RPC, for as long as
is specified by the second parameter to walletpassphrase). The wallet is
then locked (or can be manually locked using the walletlock RPC command)
and the unencrypted master key is removed from memory.
Implementation details of wallet encryption
-------------------------------------------
When the wallet is locked, calls to sendtoaddress, sendfrom, sendmany,
and keypoolrefill will return Error -13: "Error: Please enter the wallet
passphrase with walletpassphrase first."
When the wallet is unlocked, calls to walletpassphrase will fail.
When a wallet is encrypted, the passphrase is required to top up the
keypool, thus, if the passphrase is rarely entered, it is possible that
keypool might run out. In this case, the default key will be used as the
target for payouts for mining, and calls to getnewaddress and getaccount
address will return an error. In order to prevent such cases, the keypool
is automatically refilled when walletpassphrase is called with a correct
passphrase and when topupkeypool is called (while the wallet is unlocked).
Note that the keypool continues to be topped up on various occasions when
a new key from pool is used and the wallet is unlocked (or unencrypted).
See the documentation at the bitcoin wiki:
https://en.bitcoin.it/wiki/Main_Page

36
doc/build-msw.txt

@ -27,11 +27,11 @@ Dependencies @@ -27,11 +27,11 @@ Dependencies
Libraries you need to download separately and build:
default path download
wxWidgets \wxwidgets-2.9.1-mgw http://www.wxwidgets.org/downloads/
wxWidgets \wxwidgets-2.9.2-mgw http://www.wxwidgets.org/downloads/
OpenSSL \openssl-1.0.0d-mgw http://www.openssl.org/source/
Berkeley DB \db-4.7.25.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost-1.43.0-mgw http://www.boost.org/users/download/
miniupnpc \upnpc-exe-win32-20110215 http://miniupnp.tuxfamily.org/files/
Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost-1.47.0-mgw http://www.boost.org/users/download/
miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/
Their licenses:
wxWidgets LGPL 2.1 with very liberal exceptions
@ -41,11 +41,11 @@ Boost MIT-like license @@ -41,11 +41,11 @@ Boost MIT-like license
miniupnpc New (3-clause) BSD license
Versions used in this release:
wxWidgets 2.9.1
wxWidgets 2.9.2
OpenSSL 1.0.0d
Berkeley DB 4.7.25.NC
Boost 1.43.0
miniupnpc 1.5-20110215
Berkeley DB 4.8.30.NC
Boost 1.47.0
miniupnpc 1.6
Notes
@ -57,7 +57,7 @@ classes that do the rote work of constructing all the UI elements. @@ -57,7 +57,7 @@ classes that do the rote work of constructing all the UI elements.
wxWidgets
---------
DOS shell:
cd \wxWidgets-2.9.1-mgw\build\msw
cd \wxWidgets-2.9.2-mgw\build\msw
mingw32-make -f makefile.gcc
OpenSSL
@ -73,30 +73,26 @@ make @@ -73,30 +73,26 @@ make
Berkeley DB
-----------
MSYS shell:
cd /c/db-4.7.25.NC-mgw/build_unix
cd /c/db-4.8.30.NC-mgw/build_unix
sh ../dist/configure --enable-mingw --enable-cxx
make
Boost
-----
DOS prompt:
downloaded boost jam 3.1.18
cd \boost-1.43.0-mgw
cd \boost-1.47.0-mgw
bjam toolset=gcc --build-type=complete stage
Note:
building with boost 1.45.0 failed because of boost ticket 4614, 4258
builds fine with boost 1.43.0
MiniUPnPc
---------
Building miniupnpc failed on Windows Server 2003, thus it is expected that a binary copy will be used.
See http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=642
UPnP support is optional, make with USE_UPNP= to disable it.
Get upnpc-exe-win32-20110215.zip and unzip it to \upnpc-exe-win32-20110215
Get miniupnpc-1.5.20110215.tar.gz and copy *.h to \upnpc-exe-win32-20110215\miniupnpc
MSYS shell:
cd /c/miniupnpc-1.6-mgw
make -f Makefile.mingw
mkdir miniupnpc
cp *.h miniupnpc/
Bitcoin
-------

18
doc/build-osx.txt

@ -135,18 +135,18 @@ The process for miniupnpc (optional) is similar to that of OpenSSL. @@ -135,18 +135,18 @@ The process for miniupnpc (optional) is similar to that of OpenSSL.
Download from http://miniupnp.tuxfamily.org/files/.
cd ~/bitcoin/deps
tar xvf ~/Downloads/miniupnpc-1.5.tar
mv miniupnpc-1.5 miniupnpc-1.5-x86_64
tar xvf ~/Downloads/miniupnpc-1.5.tar
mv miniupnpc-1.5 miniupnpc-1.5-i386
tar xvf ~/Downloads/miniupnpc-1.6.tar
mv miniupnpc-1.6 miniupnpc-1.6-x86_64
tar xvf ~/Downloads/miniupnpc-1.6.tar
mv miniupnpc-1.6 miniupnpc-1.6-i386
# build x86_64 (64 bit intel) binary
cd miniupnpc-1.5-x86_64
cd miniupnpc-1.6-x86_64
export CFLAGS="-arch x86_64"
export LDFLAGS="-arch x86_64"
export PREFIX="/Users/macuser/bitcoin/deps"
make && make install
# build i386 (32 bit intel) binary
cd miniupnpc-1.5-i386
cd miniupnpc-1.6-i386
export CFLAGS="-arch i386"
export LDFLAGS="-arch i386"
export PREFIX="/Users/macuser/bitcoin/deps"
@ -154,7 +154,7 @@ make @@ -154,7 +154,7 @@ make
# combine the libs
cd ~/bitcoin/deps
lipo -arch i386 miniupnpc-1.5-i386/libminiupnpc.a -arch x86_64 miniupnpc-1.5-x86_64/libminiupnpc.a -o lib/libminiupnpc.a -create
lipo -arch i386 miniupnpc-1.6-i386/libminiupnpc.a -arch x86_64 miniupnpc-1.6-x86_64/libminiupnpc.a -o lib/libminiupnpc.a -create
Verify your binaries
@ -175,8 +175,8 @@ Berkeley DB @@ -175,8 +175,8 @@ Berkeley DB
Download from http://freshmeat.net/projects/berkeleydb/
cd ~/bitcoin/deps
tar xvf ~/Downloads/db-4.8.26.tar
cd db-4.8.26/build_unix
tar xvf ~/Downloads/db-4.8.30.tar
cd db-4.8.30/build_unix
../dist/configure --prefix=/Users/macosuser/bitcoin/deps --enable-cxx && make && make install

21
doc/build-unix.txt

@ -25,8 +25,8 @@ Dependencies @@ -25,8 +25,8 @@ Dependencies
sudo apt-get install build-essential
sudo apt-get install libgtk2.0-dev
sudo apt-get install libssl-dev
sudo apt-get install libdb4.7-dev
sudo apt-get install libdb4.7++-dev
sudo apt-get install libdb4.8-dev
sudo apt-get install libdb4.8++-dev
Boost 1.40+: sudo apt-get install libboost-all-dev
or Boost 1.37: sudo apt-get install libboost1.37-dev
@ -55,10 +55,10 @@ miniupnpc New (3-clause) BSD license @@ -55,10 +55,10 @@ miniupnpc New (3-clause) BSD license
Versions used in this release:
GCC 4.3.3
OpenSSL 0.9.8g
wxWidgets 2.9.0
Berkeley DB 4.7.25.NC
wxWidgets 2.9.2
Berkeley DB 4.8.30.NC
Boost 1.37
miniupnpc 1.5
miniupnpc 1.6
Notes
@ -74,8 +74,8 @@ symbols, which reduces the executable size by about 90%. @@ -74,8 +74,8 @@ symbols, which reduces the executable size by about 90%.
wxWidgets
---------
cd /usr/local
tar -xzvf wxWidgets-2.9.0.tar.gz
cd wxWidgets-2.9.0
tar -xzvf wxWidgets-2.9.2.tar.gz
cd wxWidgets-2.9.2
mkdir buildgtk
cd buildgtk
../configure --with-gtk --enable-debug --disable-shared --enable-monolithic --without-libpng --disable-svg
@ -87,8 +87,8 @@ ldconfig @@ -87,8 +87,8 @@ ldconfig
miniupnpc
---------
tar -xzvf miniupnpc-1.5.tar.gz
cd miniupnpc-1.5
tar -xzvf miniupnpc-1.6.tar.gz
cd miniupnpc-1.6
make
sudo su
make install
@ -96,8 +96,7 @@ make install @@ -96,8 +96,7 @@ make install
Berkeley DB
-----------
You need Berkeley DB 4.7. Don't use 4.8, the database/log0000* files
are incompatible. If you have to build Berkeley DB yourself:
You need Berkeley DB 4.8. If you have to build Berkeley DB yourself:
../dist/configure --enable-cxx
make

44
doc/coding.txt

@ -39,3 +39,47 @@ v vector or similar list objects @@ -39,3 +39,47 @@ v vector or similar list objects
map map or multimap
set set or multiset
bn CBigNum
-------------------------
Locking/mutex usage notes
The code is multi-threaded, and uses mutexes and the CRITICAL_BLOCK/TRY_CRITICAL_BLOCK macros to protect data structures.
Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main and then cs_wallet, while thread 2 locks them in the opposite order: result, deadlock as each waits for the other to release its lock) are a problem. Compile with -DDEBUG_LOCKORDER to get lock order inconsistencies reported in the debug.log file.
Re-architecting the core code so there are better-defined interfaces between the various components is a goal, with any necessary locking done by the components (e.g. see the self-contained CKeyStore class and its cs_KeyStore lock for example).
-------
Threads
StartNode : Starts other threads.
ThreadGetMyExternalIP : Determines outside-the-firewall IP address, sends addr message to connected peers when it determines it.
ThreadIRCSeed : Joins IRC bootstrapping channel, watching for new peers and advertising this node's IP address.
ThreadSocketHandler : Sends/Receives data from peers on port 8333.
ThreadMessageHandler : Higher-level message handling (sending and receiving).
ThreadOpenConnections : Initiates new connections to peers.
ThreadTopUpKeyPool : replenishes the keystore's keypool.
ThreadCleanWalletPassphrase : re-locks an encrypted wallet after user has unlocked it for a period of time.
SendingDialogStartTransfer : used by pay-via-ip-address code (obsolete)
ThreadDelayedRepaint : repaint the gui
ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used in 500ms.
ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them.
ThreadBitcoinMiner : Generates bitcoins
ThreadMapPort : Universal plug-and-play startup/shutdown
Shutdown : Does an orderly shutdown of everything
ExitTimeout : Windows-only, sleeps 5 seconds then exits application

636
locale/pl/LC_MESSAGES/bitcoin.po

File diff suppressed because it is too large Load Diff

642
src/bitcoinrpc.cpp

@ -331,71 +331,59 @@ Value getnewaddress(const Array& params, bool fHelp) @@ -331,71 +331,59 @@ Value getnewaddress(const Array& params, bool fHelp)
"If [account] is specified (recommended), it is added to the address book "
"so payments received with the address will be credited to [account].");
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
if (pwalletMain->GetKeyPoolSize() < 1)
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
// Parse the account first so we don't generate a key if there's an error
string strAccount;
if (params.size() > 0)
strAccount = AccountFromValue(params[0]);
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
// Generate a new key that is added to wallet
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
std::vector<unsigned char> newKey;
if (!pwalletMain->GetKeyFromPool(newKey, false))
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
CBitcoinAddress address(newKey);
// This could be done in the same main CS as GetKeyFromKeyPool.
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
pwalletMain->SetAddressBookName(address, strAccount);
pwalletMain->SetAddressBookName(address, strAccount);
return address.ToString();
}
// requires cs_main, cs_mapWallet, cs_mapAddressBook locks
CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
{
CWalletDB walletdb(pwalletMain->strWalletFile);
CAccount account;
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
walletdb.ReadAccount(strAccount, account);
walletdb.ReadAccount(strAccount, account);
bool bKeyUsed = false;
bool bKeyUsed = false;
// Check if the current key has been used
if (!account.vchPubKey.empty())
// Check if the current key has been used
if (!account.vchPubKey.empty())
{
CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
++it)
{
CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
++it)
{
const CWalletTx& wtx = (*it).second;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.scriptPubKey == scriptPubKey)
bKeyUsed = true;
}
const CWalletTx& wtx = (*it).second;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.scriptPubKey == scriptPubKey)
bKeyUsed = true;
}
}
// Generate a new key
if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
{
if (pwalletMain->GetKeyPoolSize() < 1)
{
if (bKeyUsed || bForceNew)
throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
}
else
{
account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
walletdb.WriteAccount(strAccount, account);
}
}
// Generate a new key
if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
{
if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
walletdb.WriteAccount(strAccount, account);
}
return CBitcoinAddress(account.vchPubKey);
@ -413,12 +401,7 @@ Value getaccountaddress(const Array& params, bool fHelp) @@ -413,12 +401,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
Value ret;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
ret = GetAccountAddress(strAccount).ToString();
}
ret = GetAccountAddress(strAccount).ToString();
return ret;
}
@ -442,20 +425,15 @@ Value setaccount(const Array& params, bool fHelp) @@ -442,20 +425,15 @@ Value setaccount(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[1]);
// Detect when changing the account of an address that is the 'unused current key' of another account:
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
if (pwalletMain->mapAddressBook.count(address))
{
if (pwalletMain->mapAddressBook.count(address))
{
string strOldAccount = pwalletMain->mapAddressBook[address];
if (address == GetAccountAddress(strOldAccount))
GetAccountAddress(strOldAccount, true);
}
pwalletMain->SetAddressBookName(address, strAccount);
string strOldAccount = pwalletMain->mapAddressBook[address];
if (address == GetAccountAddress(strOldAccount))
GetAccountAddress(strOldAccount, true);
}
pwalletMain->SetAddressBookName(address, strAccount);
return Value::null;
}
@ -472,12 +450,9 @@ Value getaccount(const Array& params, bool fHelp) @@ -472,12 +450,9 @@ Value getaccount(const Array& params, bool fHelp)
throw JSONRPCError(-5, "Invalid bitcoin address");
string strAccount;
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
strAccount = (*mi).second;
}
map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
strAccount = (*mi).second;
return strAccount;
}
@ -493,15 +468,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp) @@ -493,15 +468,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
// Find all addresses that have the given account
Array ret;
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
const string& strName = item.second;
if (strName == strAccount)
ret.push_back(address.ToString());
}
const CBitcoinAddress& address = item.first;
const string& strName = item.second;
if (strName == strAccount)
ret.push_back(address.ToString());
}
return ret;
}
@ -548,16 +520,12 @@ Value sendtoaddress(const Array& params, bool fHelp) @@ -548,16 +520,12 @@ Value sendtoaddress(const Array& params, bool fHelp)
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
if(pwalletMain->IsLocked())
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
}
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
return wtx.GetHash().GetHex();
}
@ -586,19 +554,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) @@ -586,19 +554,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->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())
continue;
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
return ValueFromAmount(nAmount);
@ -607,15 +572,12 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) @@ -607,15 +572,12 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
{
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
const string& strName = item.second;
if (strName == strAccount)
setAddress.insert(address);
}
const CBitcoinAddress& address = item.first;
const string& strName = item.second;
if (strName == strAccount)
setAddress.insert(address);
}
}
@ -639,21 +601,18 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) @@ -639,21 +601,18 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->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())
continue;
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
}
@ -664,27 +623,25 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) @@ -664,27 +623,25 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
{
int64 nBalance = 0;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
// Tally wallet transactions
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal())
continue;
int64 nGenerated, nReceived, nSent, nFee;
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
// Tally wallet transactions
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (!wtx.IsFinal())
continue;
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
nBalance += nReceived;
nBalance += nGenerated - nSent - nFee;
}
int64 nGenerated, nReceived, nSent, nFee;
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
// Tally internal accounting entries
nBalance += walletdb.GetAccountCreditDebit(strAccount);
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
nBalance += nReceived;
nBalance += nGenerated - nSent - nFee;
}
// Tally internal accounting entries
nBalance += walletdb.GetAccountCreditDebit(strAccount);
return nBalance;
}
@ -763,33 +720,31 @@ Value movecmd(const Array& params, bool fHelp) @@ -763,33 +720,31 @@ Value movecmd(const Array& params, bool fHelp)
if (params.size() > 4)
strComment = params[4].get_str();
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin();
int64 nNow = GetAdjustedTime();
// Debit
CAccountingEntry debit;
debit.strAccount = strFrom;
debit.nCreditDebit = -nAmount;
debit.nTime = nNow;
debit.strOtherAccount = strTo;
debit.strComment = strComment;
walletdb.WriteAccountingEntry(debit);
// Credit
CAccountingEntry credit;
credit.strAccount = strTo;
credit.nCreditDebit = nAmount;
credit.nTime = nNow;
credit.strOtherAccount = strFrom;
credit.strComment = strComment;
walletdb.WriteAccountingEntry(credit);
walletdb.TxnCommit();
}
CWalletDB walletdb(pwalletMain->strWalletFile);
walletdb.TxnBegin();
int64 nNow = GetAdjustedTime();
// Debit
CAccountingEntry debit;
debit.strAccount = strFrom;
debit.nCreditDebit = -nAmount;
debit.nTime = nNow;
debit.strOtherAccount = strTo;
debit.strComment = strComment;
walletdb.WriteAccountingEntry(debit);
// Credit
CAccountingEntry credit;
credit.strAccount = strTo;
credit.nCreditDebit = nAmount;
credit.nTime = nNow;
credit.strOtherAccount = strFrom;
credit.strComment = strComment;
walletdb.WriteAccountingEntry(credit);
walletdb.TxnCommit();
return true;
}
@ -822,23 +777,18 @@ Value sendfrom(const Array& params, bool fHelp) @@ -822,23 +777,18 @@ Value sendfrom(const Array& params, bool fHelp)
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
if(pwalletMain->IsLocked())
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (nAmount > nBalance)
throw JSONRPCError(-6, "Account has insufficient funds");
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (nAmount > nBalance)
throw JSONRPCError(-6, "Account has insufficient funds");
// Send
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
}
// Send
string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
if (strError != "")
throw JSONRPCError(-4, strError);
return wtx.GetHash().GetHex();
}
@ -889,31 +839,26 @@ Value sendmany(const Array& params, bool fHelp) @@ -889,31 +839,26 @@ Value sendmany(const Array& params, bool fHelp)
vecSend.push_back(make_pair(scriptPubKey, nAmount));
}
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
if(pwalletMain->IsLocked())
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (totalAmount > nBalance)
throw JSONRPCError(-6, "Account has insufficient funds");
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
// Send
CReserveKey keyChange(pwalletMain);
int64 nFeeRequired = 0;
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
if (!fCreated)
{
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
throw JSONRPCError(-6, "Insufficient funds");
throw JSONRPCError(-4, "Transaction creation failed");
}
if (!pwalletMain->CommitTransaction(wtx, keyChange))
throw JSONRPCError(-4, "Transaction commit failed");
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
if (totalAmount > nBalance)
throw JSONRPCError(-6, "Account has insufficient funds");
// Send
CReserveKey keyChange(pwalletMain);
int64 nFeeRequired = 0;
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
if (!fCreated)
{
if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
throw JSONRPCError(-6, "Insufficient funds");
throw JSONRPCError(-4, "Transaction creation failed");
}
if (!pwalletMain->CommitTransaction(wtx, keyChange))
throw JSONRPCError(-4, "Transaction commit failed");
return wtx.GetHash().GetHex();
}
@ -944,68 +889,62 @@ Value ListReceived(const Array& params, bool fByAccounts) @@ -944,68 +889,62 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Tally
map<CBitcoinAddress, tallyitem> mapTally;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->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())
continue;
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
int nDepth = wtx.GetDepthInMainChain();
if (nDepth < nMinDepth)
continue;
int nDepth = wtx.GetDepthInMainChain();
if (nDepth < nMinDepth)
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CBitcoinAddress address;
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
CBitcoinAddress address;
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
continue;
tallyitem& item = mapTally[address];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
}
tallyitem& item = mapTally[address];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
}
}
// Reply
Array ret;
map<string, tallyitem> mapAccountTally;
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
const CBitcoinAddress& address = item.first;
const string& strAccount = item.second;
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
if (it == mapTally.end() && !fIncludeEmpty)
continue;
const CBitcoinAddress& address = item.first;
const string& strAccount = item.second;
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
if (it == mapTally.end() && !fIncludeEmpty)
continue;
int64 nAmount = 0;
int nConf = INT_MAX;
if (it != mapTally.end())
{
nAmount = (*it).second.nAmount;
nConf = (*it).second.nConf;
}
int64 nAmount = 0;
int nConf = INT_MAX;
if (it != mapTally.end())
{
nAmount = (*it).second.nAmount;
nConf = (*it).second.nConf;
}
if (fByAccounts)
{
tallyitem& item = mapAccountTally[strAccount];
item.nAmount += nAmount;
item.nConf = min(item.nConf, nConf);
}
else
{
Object obj;
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("label", strAccount)); // deprecated
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
ret.push_back(obj);
}
if (fByAccounts)
{
tallyitem& item = mapAccountTally[strAccount];
item.nAmount += nAmount;
item.nConf = min(item.nConf, nConf);
}
else
{
Object obj;
obj.push_back(Pair("address", address.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("label", strAccount)); // deprecated
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
ret.push_back(obj);
}
}
@ -1107,27 +1046,23 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe @@ -1107,27 +1046,23 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
string account;
if (pwalletMain->mapAddressBook.count(r.first))
account = pwalletMain->mapAddressBook[r.first];
if (fAllAccounts || (account == strAccount))
{
string account;
if (pwalletMain->mapAddressBook.count(r.first))
account = pwalletMain->mapAddressBook[r.first];
if (fAllAccounts || (account == strAccount))
{
Object entry;
entry.push_back(Pair("account", account));
entry.push_back(Pair("address", r.first.ToString()));
entry.push_back(Pair("category", "receive"));
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
if (fLong)
WalletTxToJSON(wtx, entry);
ret.push_back(entry);
}
Object entry;
entry.push_back(Pair("account", account));
entry.push_back(Pair("address", r.first.ToString()));
entry.push_back(Pair("category", "receive"));
entry.push_back(Pair("amount", ValueFromAmount(r.second)));
if (fLong)
WalletTxToJSON(wtx, entry);
ret.push_back(entry);
}
}
}
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
@ -1167,41 +1102,38 @@ Value listtransactions(const Array& params, bool fHelp) @@ -1167,41 +1102,38 @@ Value listtransactions(const Array& params, bool fHelp)
Array ret;
CWalletDB walletdb(pwalletMain->strWalletFile);
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;
// 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 = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
}
list<CAccountingEntry> acentries;
walletdb.ListAccountCreditDebit(strAccount, acentries);
BOOST_FOREACH(CAccountingEntry& entry, acentries)
{
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
}
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)));
}
list<CAccountingEntry> acentries;
walletdb.ListAccountCreditDebit(strAccount, acentries);
BOOST_FOREACH(CAccountingEntry& entry, acentries)
{
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
}
// Now: iterate backwards until we have nCount items to return:
TxItems::reverse_iterator it = txByTime.rbegin();
if (txByTime.size() > nFrom) std::advance(it, nFrom);
for (; it != txByTime.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
ListTransactions(*pwtx, strAccount, 0, true, ret);
CAccountingEntry *const pacentry = (*it).second.second;
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
if (ret.size() >= nCount) break;
}
// ret is now newest to oldest
// Now: iterate backwards until we have nCount items to return:
TxItems::reverse_iterator it = txByTime.rbegin();
if (txByTime.size() > nFrom) std::advance(it, nFrom);
for (; it != txByTime.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
ListTransactions(*pwtx, strAccount, 0, true, ret);
CAccountingEntry *const pacentry = (*it).second.second;
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
if (ret.size() >= nCount) break;
}
// ret is now newest to oldest
// Make sure we return only last nCount items (sends-to-self might give us an extra):
if (ret.size() > nCount)
@ -1227,34 +1159,30 @@ Value listaccounts(const Array& params, bool fHelp) @@ -1227,34 +1159,30 @@ Value listaccounts(const Array& params, bool fHelp)
nMinDepth = params[0].get_int();
map<string, int64> mapAccountBalances;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
mapAccountBalances[entry.second] = 0;
}
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
mapAccountBalances[entry.second] = 0;
}
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->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;
string strSentAccount;
list<pair<CBitcoinAddress, int64> > listReceived;
list<pair<CBitcoinAddress, int64> > listSent;
wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
mapAccountBalances[strSentAccount] -= nFee;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
mapAccountBalances[strSentAccount] -= s.second;
if (wtx.GetDepthInMainChain() >= nMinDepth)
{
const CWalletTx& wtx = (*it).second;
int64 nGeneratedImmature, nGeneratedMature, nFee;
string strSentAccount;
list<pair<CBitcoinAddress, int64> > listReceived;
list<pair<CBitcoinAddress, int64> > listSent;
wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
mapAccountBalances[strSentAccount] -= nFee;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
mapAccountBalances[strSentAccount] -= s.second;
if (wtx.GetDepthInMainChain() >= nMinDepth)
{
mapAccountBalances[""] += nGeneratedMature;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
if (pwalletMain->mapAddressBook.count(r.first))
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
else
mapAccountBalances[""] += r.second;
}
mapAccountBalances[""] += nGeneratedMature;
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
if (pwalletMain->mapAddressBook.count(r.first))
mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
else
mapAccountBalances[""] += r.second;
}
}
@ -1281,27 +1209,25 @@ Value gettransaction(const Array& params, bool fHelp) @@ -1281,27 +1209,25 @@ Value gettransaction(const Array& params, bool fHelp)
hash.SetHex(params[0].get_str());
Object entry;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
{
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
if (!pwalletMain->mapWallet.count(hash))
throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
if (wtx.IsFromMe())
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
if (wtx.IsFromMe())
entry.push_back(Pair("fee", ValueFromAmount(nFee)));
Array details;
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
entry.push_back(Pair("details", details));
}
WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
Array details;
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
entry.push_back(Pair("details", details));
return entry;
}
@ -1332,13 +1258,10 @@ Value keypoolrefill(const Array& params, bool fHelp) @@ -1332,13 +1258,10 @@ Value keypoolrefill(const Array& params, bool fHelp)
"keypoolrefill\n"
"Fills the keypool.");
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
pwalletMain->TopUpKeyPool();
}
pwalletMain->TopUpKeyPool();
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
throw JSONRPCError(-4, "Error refreshing keypool.");
@ -1407,24 +1330,21 @@ Value walletpassphrase(const Array& params, bool fHelp) @@ -1407,24 +1330,21 @@ Value walletpassphrase(const Array& params, bool fHelp)
mlock(&strWalletPass[0], strWalletPass.capacity());
strWalletPass = params[0].get_str();
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
if (strWalletPass.length() > 0)
{
if (strWalletPass.length() > 0)
if (!pwalletMain->Unlock(strWalletPass))
{
if (!pwalletMain->Unlock(strWalletPass))
{
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
munlock(&strWalletPass[0], strWalletPass.capacity());
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
}
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
munlock(&strWalletPass[0], strWalletPass.capacity());
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
}
else
throw runtime_error(
"walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds.");
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
munlock(&strWalletPass[0], strWalletPass.capacity());
}
else
throw runtime_error(
"walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds.");
CreateThread(ThreadTopUpKeyPool, NULL);
int* pnSleepTime = new int(params[1].get_int());
@ -1553,11 +1473,8 @@ Value validateaddress(const Array& params, bool fHelp) @@ -1553,11 +1473,8 @@ Value validateaddress(const Array& params, bool fHelp)
string currentAddress = address.ToString();
ret.push_back(Pair("address", currentAddress));
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
if (pwalletMain->mapAddressBook.count(address))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
}
if (pwalletMain->mapAddressBook.count(address))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
}
return ret;
}
@ -2233,7 +2150,10 @@ void ThreadRPCServer2(void* parg) @@ -2233,7 +2150,10 @@ void ThreadRPCServer2(void* parg)
try
{
// Execute
Value result = (*(*mi).second)(params, false);
Value result;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
result = (*(*mi).second)(params, false);
// Send reply
string strReply = JSONRPCReply(result, Value::null, id);

3
src/db.cpp

@ -683,8 +683,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet) @@ -683,8 +683,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
#endif
//// todo: shouldn't we catch exceptions and try to recover and continue?
CRITICAL_BLOCK(pwallet->cs_mapWallet)
CRITICAL_BLOCK(pwallet->cs_KeyStore)
CRITICAL_BLOCK(pwallet->cs_wallet)
{
// Get cursor
Dbc* pcursor = GetCursor();

21
src/keystore.cpp

@ -33,6 +33,19 @@ bool CBasicKeyStore::AddKey(const CKey& key) @@ -33,6 +33,19 @@ bool CBasicKeyStore::AddKey(const CKey& key)
return true;
}
bool CCryptoKeyStore::SetCrypted()
{
CRITICAL_BLOCK(cs_KeyStore)
{
if (fUseCrypto)
return true;
if (!mapKeys.empty())
return false;
fUseCrypto = true;
}
return true;
}
std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
{
RandAddSeedPerfmon();
@ -45,7 +58,7 @@ std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey() @@ -45,7 +58,7 @@ std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_KeyStore)
{
if (!SetCrypted())
return false;
@ -72,7 +85,6 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) @@ -72,7 +85,6 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
bool CCryptoKeyStore::AddKey(const CKey& key)
{
CRITICAL_BLOCK(cs_KeyStore)
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!IsCrypted())
return CBasicKeyStore::AddKey(key);
@ -106,7 +118,7 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, @@ -106,7 +118,7 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
{
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_KeyStore)
{
if (!IsCrypted())
return CBasicKeyStore::GetKey(address, keyOut);
@ -128,7 +140,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const @@ -128,7 +140,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
{
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_KeyStore)
{
if (!IsCrypted())
return CKeyStore::GetPubKey(address, vchPubKeyOut);
@ -146,7 +158,6 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi @@ -146,7 +158,6 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
CRITICAL_BLOCK(cs_KeyStore)
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!mapCryptedKeys.empty() || IsCrypted())
return false;

54
src/keystore.h

@ -9,9 +9,10 @@ @@ -9,9 +9,10 @@
class CKeyStore
{
public:
protected:
mutable CCriticalSection cs_KeyStore;
public:
virtual bool AddKey(const CKey& key) =0;
virtual bool HaveKey(const CBitcoinAddress &address) const =0;
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
@ -30,15 +31,21 @@ public: @@ -30,15 +31,21 @@ public:
bool AddKey(const CKey& key);
bool HaveKey(const CBitcoinAddress &address) const
{
return (mapKeys.count(address) > 0);
bool result;
CRITICAL_BLOCK(cs_KeyStore)
result = (mapKeys.count(address) > 0);
return result;
}
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const
{
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end())
CRITICAL_BLOCK(cs_KeyStore)
{
keyOut.SetSecret((*mi).second);
return true;
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end())
{
keyOut.SetSecret((*mi).second);
return true;
}
}
return false;
}
@ -58,15 +65,7 @@ private: @@ -58,15 +65,7 @@ private:
bool fUseCrypto;
protected:
bool SetCrypted()
{
if (fUseCrypto)
return true;
if (!mapKeys.empty())
return false;
fUseCrypto = true;
return true;
}
bool SetCrypted();
// will encrypt previously unencrypted keys
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
@ -74,8 +73,6 @@ protected: @@ -74,8 +73,6 @@ protected:
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
public:
mutable CCriticalSection cs_vMasterKey; //No guarantees master key wont get locked before you can use it, so lock this first
CCryptoKeyStore() : fUseCrypto(false)
{
}
@ -89,18 +86,20 @@ public: @@ -89,18 +86,20 @@ public:
{
if (!IsCrypted())
return false;
return vMasterKey.empty();
bool result;
CRITICAL_BLOCK(cs_KeyStore)
result = vMasterKey.empty();
return result;
}
bool Lock()
{
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!SetCrypted())
return false;
if (!SetCrypted())
return false;
CRITICAL_BLOCK(cs_KeyStore)
vMasterKey.clear();
}
return true;
}
@ -109,9 +108,12 @@ public: @@ -109,9 +108,12 @@ public:
bool AddKey(const CKey& key);
bool HaveKey(const CBitcoinAddress &address) const
{
if (!IsCrypted())
return CBasicKeyStore::HaveKey(address);
return mapCryptedKeys.count(address) > 0;
CRITICAL_BLOCK(cs_KeyStore)
{
if (!IsCrypted())
return CBasicKeyStore::HaveKey(address);
return mapCryptedKeys.count(address) > 0;
}
}
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;

24
src/main.cpp

@ -22,15 +22,15 @@ set<CWallet*> setpwalletRegistered; @@ -22,15 +22,15 @@ set<CWallet*> setpwalletRegistered;
CCriticalSection cs_main;
map<uint256, CTransaction> mapTransactions;
static map<uint256, CTransaction> mapTransactions;
CCriticalSection cs_mapTransactions;
unsigned int nTransactionsUpdated = 0;
map<COutPoint, CInPoint> mapNextTx;
map<uint256, CBlockIndex*> mapBlockIndex;
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
int nTotalBlocksEstimate = 134444; // Conservative estimate of total nr of blocks on main chain
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
const int nTotalBlocksEstimate = 140700; // 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;
@ -295,9 +295,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) @@ -295,9 +295,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
bool CTransaction::CheckTransaction() const
{
// Basic checks that don't depend on any context
if (vin.empty() || vout.empty())
return error("CTransaction::CheckTransaction() : vin or vout empty");
if (vin.empty())
return error("CTransaction::CheckTransaction() : vin empty");
if (vout.empty())
return error("CTransaction::CheckTransaction() : vout empty");
// Size limits
if (::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE)
return error("CTransaction::CheckTransaction() : size limits failed");
@ -1301,7 +1302,8 @@ bool CBlock::AcceptBlock() @@ -1301,7 +1302,8 @@ bool CBlock::AcceptBlock()
(nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")) ||
(nHeight == 105000 && hash != uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")) ||
(nHeight == 118000 && hash != uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553")) ||
(nHeight == 134444 && hash != uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")))
(nHeight == 134444 && hash != uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")) ||
(nHeight == 140700 && hash != uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd")))
return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
// Write block to history file
@ -1318,7 +1320,7 @@ bool CBlock::AcceptBlock() @@ -1318,7 +1320,7 @@ bool CBlock::AcceptBlock()
if (hashBestChain == hash)
CRITICAL_BLOCK(cs_vNodes)
BOOST_FOREACH(CNode* pnode, vNodes)
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 134444))
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 140700))
pnode->PushInventory(CInv(MSG_BLOCK, hash));
return true;
@ -2185,7 +2187,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2185,7 +2187,7 @@ bool static 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] = pwalletMain->GetOrReuseKeyFromPool();
pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr.ip], true);
// Send back approval of order and pubkey to use
CScript scriptPubKey;
@ -2627,7 +2629,7 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1 @@ -2627,7 +2629,7 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1
}
}
// Some explaining would be appreciated
class COrphan
{
public:
@ -2883,7 +2885,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) @@ -2883,7 +2885,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
reservekey.KeepKey();
// Track how many getdata requests this block gets
CRITICAL_BLOCK(wallet.cs_mapRequestCount)
CRITICAL_BLOCK(wallet.cs_wallet)
wallet.mapRequestCount[pblock->GetHash()] = 0;
// Process this block the same as if we had received it from another node

14
src/main.h

@ -21,7 +21,6 @@ class CKeyItem; @@ -21,7 +21,6 @@ class CKeyItem;
class CReserveKey;
class CWalletDB;
class CMessageHeader;
class CAddress;
class CInv;
class CRequestTracker;
@ -54,7 +53,6 @@ static const int fHaveUPnP = false; @@ -54,7 +53,6 @@ static const int fHaveUPnP = false;
extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
extern uint256 hashGenesisBlock;
extern CBigNum bnProofOfWorkLimit;
extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern CBigNum bnBestChainWork;
@ -1558,16 +1556,4 @@ public: @@ -1558,16 +1556,4 @@ public:
bool ProcessAlert();
};
extern std::map<uint256, CTransaction> mapTransactions;
#endif

60
src/makefile.linux-mingw

@ -7,19 +7,19 @@ DEPSDIR:=/usr/i586-mingw32msvc @@ -7,19 +7,19 @@ DEPSDIR:=/usr/i586-mingw32msvc
USE_UPNP:=0
INCLUDEPATHS= \
-I"$(DEPSDIR)/boost_1_43_0" \
-I"$(DEPSDIR)/db-4.7.25.NC/build_unix" \
-I"$(DEPSDIR)/boost_1_47_0" \
-I"$(DEPSDIR)/db-4.8.30.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)/wxWidgets-2.9.2/lib/gcc_lib/mswud" \
-I"$(DEPSDIR)/wxWidgets-2.9.2/include" \
-I"$(DEPSDIR)/wxWidgets-2.9.2/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)/boost_1_47_0/stage/lib" \
-L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
-L"$(DEPSDIR)/openssl-1.0.0d" \
-L"$(DEPSDIR)/wxWidgets-2.9.1/lib"
-L"$(DEPSDIR)/wxWidgets-2.9.2/lib"
WXLIBS= -l wx_mswu-2.9-i586-mingw32msvc
@ -32,16 +32,35 @@ LIBS= \ @@ -32,16 +32,35 @@ LIBS= \
-l ssl \
-l crypto
DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
DEFS=-D_MT -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
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 \
crypter.h init.h
HEADERS = \
base58.h \
bignum.h \
crypter.h \
db.h \
headers.h \
init.h \
irc.h \
key.h \
keystore.h \
main.h \
net.h \
noui.h \
protocol.h \
rpc.h \
script.h \
serialize.h \
strlcpy.h \
ui.h \
uibase.h \
uint256.h \
util.h \
wallet.h
ifdef USE_UPNP
INCLUDEPATHS += -I"$(DEPSDIR)/upnpc-exe-win32-20110215"
LIBPATHS += -L"$(DEPSDIR)/upnpc-exe-win32-20110215"
LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
LIBS += -l miniupnpc -l iphlpapi
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
@ -49,17 +68,18 @@ endif @@ -49,17 +68,18 @@ 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/crypter.o \
obj/db.o \
obj/net.o \
obj/init.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/init.o \
obj/crypter.o \
obj/script.o \
obj/util.o \
obj/wallet.o \
cryptopp/obj/sha.o \
cryptopp/obj/cpu.o

67
src/makefile.mingw

@ -5,40 +5,60 @@ @@ -5,40 +5,60 @@
USE_UPNP:=0
INCLUDEPATHS= \
-I"C:\boost-1.43.0-mgw" \
-I"C:\db-4.7.25.NC-mgw\build_unix" \
-I"C:\boost-1.47.0-mgw" \
-I"C:\db-4.8.30.NC-mgw\build_unix" \
-I"C:\openssl-1.0.0d-mgw\include" \
-I"C:\wxWidgets-2.9.1-mgw\lib\gcc_lib\mswud" \
-I"C:\wxWidgets-2.9.1-mgw\include"
-I"C:\wxWidgets-2.9.2-mgw\lib\gcc_lib\mswud" \
-I"C:\wxWidgets-2.9.2-mgw\include"
LIBPATHS= \
-L"C:\boost-1.43.0-mgw\stage\lib" \
-L"C:\db-4.7.25.NC-mgw\build_unix" \
-L"C:\boost-1.47.0-mgw\stage\lib" \
-L"C:\db-4.8.30.NC-mgw\build_unix" \
-L"C:\openssl-1.0.0d-mgw" \
-L"C:\wxWidgets-2.9.1-mgw\lib\gcc_lib"
-L"C:\wxWidgets-2.9.2-mgw\lib\gcc_lib"
WXLIBS= \
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd
LIBS= \
-l boost_system-mgw45-mt-s-1_43 \
-l boost_filesystem-mgw45-mt-s-1_43 \
-l boost_program_options-mgw45-mt-s-1_43 \
-l boost_thread-mgw45-mt-s-1_43 \
-l boost_system-mgw45-mt-s-1_47 \
-l boost_filesystem-mgw45-mt-s-1_47 \
-l boost_program_options-mgw45-mt-s-1_47 \
-l boost_thread-mgw45-mt-s-1_47 \
-l db_cxx \
-l ssl \
-l crypto
DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL
DEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
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 keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h \
init.h crypter.h
HEADERS = \
base58.h \
bignum.h \
crypter.h \
db.h \
headers.h \
init.h \
irc.h \
key.h \
keystore.h \
main.h \
net.h \
noui.h \
protocol.h \
rpc.h \
script.h \
serialize.h \
strlcpy.h \
ui.h \
uibase.h \
uint256.h \
util.h \
wallet.h
ifdef USE_UPNP
INCLUDEPATHS += -I"C:\upnpc-exe-win32-20110215"
LIBPATHS += -L"C:\upnpc-exe-win32-20110215"
INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw"
LIBPATHS += -L"C:\miniupnpc-1.6-mgw"
LIBS += -l miniupnpc -l iphlpapi
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
endif
@ -46,17 +66,18 @@ endif @@ -46,17 +66,18 @@ endif
LIBS += -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/crypter.o \
obj/db.o \
obj/net.o \
obj/init.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/init.o \
obj/crypter.o \
obj/script.o \
obj/util.o \
obj/wallet.o \
cryptopp/obj/sha.o \
cryptopp/obj/cpu.o

39
src/makefile.osx vendored

@ -32,22 +32,43 @@ DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_ @@ -32,22 +32,43 @@ DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_
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 keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h \
init.h crypter.h
HEADERS = \
base58.h \
bignum.h \
crypter.h \
db.h \
headers.h \
init.h \
irc.h \
key.h \
keystore.h \
main.h \
net.h \
noui.h \
protocol.h \
rpc.h \
script.h \
serialize.h \
strlcpy.h \
ui.h \
uibase.h \
uint256.h \
util.h \
wallet.h
OBJS= \
obj/util.o \
obj/script.o \
obj/crypter.o \
obj/db.o \
obj/net.o \
obj/init.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/init.o \
obj/crypter.o \
obj/script.o \
obj/util.o \
obj/wallet.o \
cryptopp/obj/sha.o \
cryptopp/obj/cpu.o

39
src/makefile.unix

@ -38,22 +38,43 @@ LIBS+= \ @@ -38,22 +38,43 @@ 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 keystore.h main.h wallet.h rpc.h uibase.h ui.h noui.h \
init.h crypter.h
HEADERS = \
base58.h \
bignum.h \
crypter.h \
db.h \
headers.h \
init.h \
irc.h \
key.h \
keystore.h \
main.h \
net.h \
noui.h \
protocol.h \
rpc.h \
script.h \
serialize.h \
strlcpy.h \
ui.h \
uibase.h \
uint256.h \
util.h \
wallet.h
OBJS= \
obj/util.o \
obj/script.o \
obj/crypter.o \
obj/db.o \
obj/net.o \
obj/init.o \
obj/irc.o \
obj/keystore.o \
obj/main.o \
obj/wallet.o \
obj/net.o \
obj/protocol.o \
obj/rpc.o \
obj/init.o \
obj/crypter.o \
obj/script.o \
obj/util.o \
obj/wallet.o \
cryptopp/obj/sha.o \
cryptopp/obj/cpu.o

50
src/makefile.vc

@ -45,21 +45,45 @@ LIBS=$(LIBS) \ @@ -45,21 +45,45 @@ LIBS=$(LIBS) \
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 wallet.h keystore.h crypter.h
HEADERS = \
base58.h \
bignum.h \
crypter.h \
db.h \
headers.h \
init.h \
irc.h \
key.h \
keystore.h \
main.h \
net.h \
noui.h \
protocol.h \
rpc.h \
script.h \
serialize.h \
strlcpy.h \
ui.h \
uibase.h \
uint256.h \
util.h \
wallet.h
OBJS= \
obj\util.obj \
obj\script.obj \
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\crypter.obj
obj\crypter.o \
obj\db.o \
obj\init.o \
obj\irc.o \
obj\keystore.o \
obj\main.o \
obj\net.o \
obj\rpc.o \
obj\protocol.o \
obj\script.o \
obj\util.o \
obj\wallet.o \
cryptopp\obj\sha.o \
cryptopp\obj\cpu.o
CRYPTOPP_OBJS= \
cryptopp\obj\sha.obj \

128
src/net.cpp

@ -12,11 +12,6 @@ @@ -12,11 +12,6 @@
#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
@ -50,10 +45,10 @@ bool fClient = false; @@ -50,10 +45,10 @@ bool fClient = false;
bool fAllowDNS = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
CNode* pnodeLocalHost = NULL;
static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
static SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
@ -1079,10 +1074,11 @@ void ThreadMapPort2(void* parg) @@ -1079,10 +1074,11 @@ void ThreadMapPort2(void* parg)
const char * rootdescurl = 0;
const char * multicastif = 0;
const char * minissdpdpath = 0;
int error = 0;
struct UPNPDev * devlist = 0;
char lanaddr[64];
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
struct UPNPUrls urls;
struct IGDdatas data;
@ -1094,14 +1090,9 @@ void ThreadMapPort2(void* parg) @@ -1094,14 +1090,9 @@ void ThreadMapPort2(void* parg)
char intClient[16];
char intPort[6];
string strDesc = "Bitcoin " + FormatFullVersion();
#ifndef __WXMSW__
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port, port, lanaddr, strDesc.c_str(), "TCP", 0);
#else
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port, port, lanaddr, r, strupnperror(r));
@ -1202,46 +1193,70 @@ void DNSAddressSeed() @@ -1202,46 +1193,70 @@ void DNSAddressSeed()
unsigned int pnSeed[] =
{
0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57,
0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018,
0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041,
0xc1d12b42, 0x86ba1243, 0x6be4df43, 0x6d4cef43, 0xd18e0644, 0x1ab0b344, 0x6584a345, 0xe7c1a445,
0x58cea445, 0xc5daa445, 0x21dda445, 0x3d3b5346, 0x13e55347, 0x1080d24a, 0x8e611e4b, 0x81518e4b,
0x6c839e4b, 0xe2ad0a4c, 0xfbbc0a4c, 0x7f5b6e4c, 0x7244224e, 0x1300554e, 0x20690652, 0x5a48b652,
0x75c5c752, 0x4335cc54, 0x340fd154, 0x87c07455, 0x087b2b56, 0x8a133a57, 0xac23c257, 0x70374959,
0xfb63d45b, 0xb9a1685c, 0x180d765c, 0x674f645d, 0x04d3495e, 0x1de44b5e, 0x4ee8a362, 0x0ded1b63,
0xc1b04b6d, 0x8d921581, 0x97b7ea82, 0x1cf83a8e, 0x91490bad, 0x09dc75ae, 0x9a6d79ae, 0xa26d79ae,
0x0fd08fae, 0x0f3e3fb2, 0x4f944fb2, 0xcca448b8, 0x3ecd6ab8, 0xa9d5a5bc, 0x8d0119c1, 0x045997d5,
0xca019dd9, 0x0d526c4d, 0xabf1ba44, 0x66b1ab55, 0x1165f462, 0x3ed7cbad, 0xa38fae6e, 0x3bd2cbad,
0xd36f0547, 0x20df7840, 0x7a337742, 0x549f8e4b, 0x9062365c, 0xd399f562, 0x2b5274a1, 0x8edfa153,
0x3bffb347, 0x7074bf58, 0xb74fcbad, 0x5b5a795b, 0x02fa29ce, 0x5a6738d4, 0xe8a1d23e, 0xef98c445,
0x4b0f494c, 0xa2bc1e56, 0x7694ad63, 0xa4a800c3, 0x05fda6cd, 0x9f22175e, 0x364a795b, 0x536285d5,
0xac44c9d4, 0x0b06254d, 0x150c2fd4, 0x32a50dcc, 0xfd79ce48, 0xf15cfa53, 0x66c01e60, 0x6bc26661,
0xc03b47ae, 0x4dda1b81, 0x3285a4c1, 0x883ca96d, 0x35d60a4c, 0xdae09744, 0x2e314d61, 0x84e247cf,
0x6c814552, 0x3a1cc658, 0x98d8f382, 0xe584cb5b, 0x15e86057, 0x7b01504e, 0xd852dd48, 0x56382f56,
0x0a5df454, 0xa0d18d18, 0x2e89b148, 0xa79c114c, 0xcbdcd054, 0x5523bc43, 0xa9832640, 0x8a066144,
0x3894c3bc, 0xab76bf58, 0x6a018ac1, 0xfebf4f43, 0x2f26c658, 0x31102f4e, 0x85e929d5, 0x2a1c175e,
0xfc6c2cd1, 0x27b04b6d, 0xdf024650, 0x161748b8, 0x28be6580, 0x57be6580, 0x1cee677a, 0xaa6bb742,
0x9a53964b, 0x0a5a2d4d, 0x2434c658, 0x9a494f57, 0x1ebb0e48, 0xf610b85d, 0x077ecf44, 0x085128bc,
0x5ba17a18, 0x27ca1b42, 0xf8a00b56, 0xfcd4c257, 0xcf2fc15e, 0xd897e052, 0x4cada04f, 0x2f35f6d5,
0x382ce8c9, 0xe523984b, 0x3f946846, 0x60c8be43, 0x41da6257, 0xde0be142, 0xae8a544b, 0xeff0c254,
0x1e0f795b, 0xaeb28890, 0xca16acd9, 0x1e47ddd8, 0x8c8c4829, 0xd27dc747, 0xd53b1663, 0x4096b163,
0x9c8dd958, 0xcb12f860, 0x9e79305c, 0x40c1a445, 0x4a90c2bc, 0x2c3a464d, 0x2727f23c, 0x30b04b6d,
0x59024cb8, 0xa091e6ad, 0x31b04b6d, 0xc29d46a6, 0x63934fb2, 0xd9224dbe, 0x9f5910d8, 0x7f530a6b,
0x752e9c95, 0x65453548, 0xa484be46, 0xce5a1b59, 0x710e0718, 0x46a13d18, 0xdaaf5318, 0xc4a8ff53,
0x87abaa52, 0xb764cf51, 0xb2025d4a, 0x6d351e41, 0xc035c33e, 0xa432c162, 0x61ef34ae, 0xd16fddbc,
0x0870e8c1, 0x3070e8c1, 0x9c71e8c1, 0xa4992363, 0x85a1f663, 0x4184e559, 0x18d96ed8, 0x17b8dbd5,
0x60e7cd18, 0xe5ee104c, 0xab17ac62, 0x1e786e1b, 0x5d23b762, 0xf2388fae, 0x88270360, 0x9e5b3d80,
0x7da518b2, 0xb5613b45, 0x1ad41f3e, 0xd550854a, 0x8617e9a9, 0x925b229c, 0xf2e92542, 0x47af0544,
0x73b5a843, 0xb9b7a0ad, 0x03a748d0, 0x0a6ff862, 0x6694df62, 0x3bfac948, 0x8e098f4f, 0x746916c3,
0x02f38e4f, 0x40bb1243, 0x6a54d162, 0x6008414b, 0xa513794c, 0x514aa343, 0x63781747, 0xdbb6795b,
0xed065058, 0x42d24b46, 0x1518794c, 0x9b271681, 0x73e4ffad, 0x0654784f, 0x438dc945, 0x641846a6,
0x2d1b0944, 0x94b59148, 0x8d369558, 0xa5a97662, 0x8b705b42, 0xce9204ae, 0x8d584450, 0x2df61555,
0xeebff943, 0x2e75fb4d, 0x3ef8fc57, 0x9921135e, 0x8e31042e, 0xb5afad43, 0x89ecedd1, 0x9cfcc047,
0x8fcd0f4c, 0xbe49f5ad, 0x146a8d45, 0x98669ab8, 0x98d9175e, 0xd1a8e46d, 0x839a3ab8, 0x40a0016c,
0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c,
0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1,
0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad,
0x6884ac63, 0x3ffecead, 0x2919b953, 0x0942fe50, 0x7a1d922e, 0xcdd6734a, 0x953a5bb6, 0x2c46922e,
0xe2a5f143, 0xaa39103a, 0xa06afa5c, 0x135ffd59, 0xe8e82863, 0xf61ef029, 0xf75f042e, 0x2b363532,
0x29b2df42, 0x16b1f64e, 0xd46e281b, 0x5280bf58, 0x60372229, 0x1be58e4f, 0xa8496f45, 0x1fb1a057,
0x756b3844, 0x3bb79445, 0x0b375518, 0xcccb0102, 0xb682bf2e, 0x46431c02, 0x3a81073a, 0xa3771f1f,
0x213a121f, 0x85dc2c1b, 0x56b4323b, 0xb34e8945, 0x3c40b33d, 0xfa276418, 0x1f818d29, 0xebe1e344,
0xf6160a18, 0xf4fa384a, 0x34b09558, 0xb882b543, 0xe3ce2253, 0x6abf56d8, 0xe91b1155, 0x688ee6ad,
0x2efc6058, 0x4792cd47, 0x0c32f757, 0x4c813a46, 0x8c93644a, 0x37507444, 0x813ad218, 0xdac06d4a,
0xe4c63e4b, 0x21a1ea3c, 0x8d88556f, 0x30e9173a, 0x041f681b, 0xdc77ba50, 0xc0072753, 0xceddd44f,
0x052d1743, 0xe3c77a4a, 0x13981c3a, 0x5685d918, 0x3c0e4e70, 0x3e56fb54, 0xb676ae0c, 0xac93c859,
0x22279f43, 0x975a4542, 0xe527f071, 0xea162f2e, 0x3c65a32e, 0x5be5713b, 0x961ec418, 0xb202922e,
0x5ef7be50, 0xce49f53e, 0x05803b47, 0x8463b055, 0x78576153, 0x3ec2ae3a, 0x4bbd7118, 0xafcee043,
0x56a3e8ba, 0x6174de4d, 0x8d01ba4b, 0xc9af564e, 0xdbc9c547, 0xa627474d, 0xdada9244, 0xd3b3083a,
0x523e071f, 0xd6b96f18, 0xbd527c46, 0xdf2bbb4d, 0xd37b4a4b, 0x3a6a2158, 0xc064b055, 0x18a8e055,
0xec4dae3b, 0x0540416c, 0x475b4fbe, 0x064803b2, 0x48e9f062, 0x2898524b, 0xd315ff43, 0xf786d247,
0xc7ea2f3e, 0xc087f043, 0xc163354b, 0x8250284d, 0xed300029, 0xbf36e05c, 0x8eb3ae4c, 0xe7aa623e,
0x7ced0274, 0xdd362c1b, 0x362b995a, 0xca26b629, 0x3fc41618, 0xb97b364e, 0xa05b8729, 0x0f5e3c43,
0xdf942618, 0x6aeb9b5b, 0xbf04762e, 0xfaaeb118, 0x87579958, 0x76520044, 0xc2660c5b, 0x628b201b,
0xf193932e, 0x1c0ad045, 0xff908346, 0x8da9d4da, 0xed201c1f, 0xa47a2b1b, 0x330007d4, 0x8ba1ed47,
0xb2f02d44, 0x7db62c1b, 0x781c454b, 0xc0300029, 0xb7062a45, 0x88b52e3a, 0x78dd6b63, 0x1cb9b718,
0x5d358e47, 0x59912c3b, 0x79607544, 0x5197f759, 0xc023be48, 0xd1013743, 0x0f354057, 0x8e3aac3b,
0x4114693e, 0x22316318, 0xe27dda50, 0x878eac3b, 0x4948a21f, 0x5db7f24c, 0x8ccb6157, 0x26a5de18,
0x0a11bd43, 0x27bb1e41, 0x60a7a951, 0x3e16b35e, 0x07888b53, 0x5648a853, 0x0149fe50, 0xd070a34f,
0x6454c96d, 0xd6e54758, 0xa96dc152, 0x65447861, 0xf6bdf95e, 0x10400202, 0x2c29d483, 0x18174732,
0x1d840618, 0x12e61818, 0x089d3f3c, 0x917e931f, 0xd1b0c90e, 0x25bd3c42, 0xeb05775b, 0x7d550c59,
0x6cfacb01, 0xe4224444, 0xa41dd943, 0x0f5aa643, 0x5e33731b, 0x81036d50, 0x6f46a0d1, 0x7731be43,
0x14840e18, 0xf1e8d059, 0x661d2b1f, 0x40a3201b, 0x9407b843, 0xedf0254d, 0x7bd1a5bc, 0x073dbe51,
0xe864a97b, 0x2efd947b, 0xb9ca0e45, 0x4e2113ad, 0xcc305731, 0xd39ca63c, 0x733df918, 0xda172b1f,
0xaa03b34d, 0x7230fd4d, 0xf1ce6e3a, 0x2e9fab43, 0xa4010750, 0xa928bd18, 0x6809be42, 0xb19de348,
0xff956270, 0x0d795f51, 0xd2dec247, 0x6df5774b, 0xbac11f79, 0xdfb05c75, 0x887683d8, 0xa1e83632,
0x2c0f7671, 0x28bcb65d, 0xac2a7545, 0x3eebfc60, 0x304ad7c4, 0xa215a462, 0xc86f0f58, 0xcfb92ebe,
0x5e23ed82, 0xf506184b, 0xec0f19b7, 0x060c59ad, 0x86ee3174, 0x85380774, 0xa199a562, 0x02b507ae,
0x33eb2163, 0xf2112b1f, 0xb702ba50, 0x131b9618, 0x90ccd04a, 0x08f3273b, 0xecb61718, 0x64b8b44d,
0x182bf4dc, 0xc7b68286, 0x6e318d5f, 0xfdb03654, 0xb3272e54, 0xe014ad4b, 0x274e4a31, 0x7806375c,
0xbc34a748, 0x1b5ad94a, 0x6b54d10e, 0x73e2ae6e, 0x5529d483, 0x8455a76d, 0x99c13f47, 0x1d811741,
0xa9782a78, 0x0b00464d, 0x7266ea50, 0x532dab46, 0x33e1413e, 0x780d0c18, 0x0fb0854e, 0x03370155,
0x2693042e, 0xfa3d824a, 0x2bb1681b, 0x37ea2a18, 0x7fb8414b, 0x32e0713b, 0xacf38d3f, 0xa282716f,
0xb1a09d7b, 0xa04b764b, 0x83c94d18, 0x05ee4c6d, 0x0e795f51, 0x46984352, 0xf80fc247, 0x3fccb946,
0xd7ae244b, 0x0a8e0a4c, 0x57b141bc, 0x3647bed1, 0x1431b052, 0x803a8bbb, 0xfc69056b, 0xf5991862,
0x14963b2e, 0xd35d5dda, 0xc6c73574, 0xc8f1405b, 0x0ca4224d, 0xecd36071, 0xa9461754, 0xe7a0ed72,
0x559e8346, 0x1c9beec1, 0xc786ea4a, 0x9561b44d, 0x9788074d, 0x1a69934f, 0x23c5614c, 0x07c79d4b,
0xc7ee52db, 0xc72df351, 0xcb135e44, 0xa0988346, 0xc211fc4c, 0x87dec34b, 0x1381074d, 0x04a65cb7,
0x4409083a, 0x4a407a4c, 0x92b8d37d, 0xacf50b4d, 0xa58aa5bc, 0x448f801f, 0x9c83762e, 0x6fd5734a,
0xfe2d454b, 0x84144c55, 0x05190e4c, 0xb2151448, 0x63867a3e, 0x16099018, 0x9c010d3c, 0x962d8f3d,
0xd51ee453, 0x9d86801f, 0x68e87b47, 0x6bf7bb73, 0x5fc7910e, 0x10d90118, 0x3db04442, 0x729d3e4b,
0xc397d842, 0x57bb15ad, 0x72f31f4e, 0xc9380043, 0x2bb24e18, 0xd9b8ab50, 0xb786801f, 0xf4dc4847,
0x85f4bb51, 0x4435995b, 0x5ba07e40, 0x2c57392e, 0x3628124b, 0x9839b64b, 0x6fe8b24d, 0xaddce847,
0x75260e45, 0x0c572a43, 0xfea21902, 0xb9f9742e, 0x5a70d443, 0x8fc5910e, 0x868d4744, 0x56245e02,
0xd7eb5f02, 0x35c12c1b, 0x4373034b, 0x8786554c, 0xa6facf18, 0x4b11a31f, 0x3570664e, 0x5a64bc42,
0x0b03983f, 0x8f457e4c, 0x0fd874c3, 0xb6cf31b2, 0x2bbc2d4e, 0x146ca5b2, 0x9d00b150, 0x048a4153,
0xca4dcd43, 0xc1607cca, 0x8234cf57, 0x9c7daead, 0x3dc07658, 0xea5c6e4c, 0xf1a0084e, 0x16d2ee53,
0x1b849418, 0xfe913a47, 0x1e988f62, 0x208b644c, 0xc55ee980, 0xbdbce747, 0xf59a384e, 0x0f56091b,
0x7417b745, 0x0c37344e, 0x2c62ab47, 0xf8533a4d, 0x8030084d, 0x76b93c4b, 0xda6ea0ad, 0x3c54f618,
0x63b0de1f, 0x7370d858, 0x1a70bb4c, 0xdda63b2e, 0x60b2ba50, 0x1ba7d048, 0xbe1b2c1b, 0xabea5747,
0x29ad2e4d, 0xe8cd7642, 0x66c80e18, 0x138bf34a, 0xc6145e44, 0x2586794c, 0x07bc5478, 0x0da0b14d,
0x8f95354e, 0x9eb11c62, 0xa1545e46, 0x2e7a2602, 0x408c9c3d, 0x59065d55, 0xf51d1a4c, 0x3bbc6a4e,
0xc71b2a2e, 0xcdaaa545, 0x17d659d0, 0x5202e7ad, 0xf1b68445, 0x93375961, 0xbd88a043, 0x066ad655,
0x890f6318, 0x7b7dca47, 0x99bdd662, 0x3bb4fc53, 0x1231efdc, 0xc0a99444, 0x96bbea47, 0x61ed8748,
0x27dfa73b, 0x8d4d1754, 0x3460042e, 0x551f0c4c, 0x8d0e0718, 0x162ddc53, 0x53231718, 0x1ecd65d0,
0x944d28bc, 0x3b79d058, 0xaff97fbc, 0x4860006c, 0xc101c90e, 0xace41743, 0xa5975d4c, 0x5cc2703e,
0xb55a4450, 0x02d18840, 0xee2765ae, 0xd6012fd5, 0x24c94d7d, 0x8c6eec47, 0x7520ba5d, 0x9e15e460,
0x8510b04c, 0x75ec3847, 0x1dfa6661, 0xe172b3ad, 0x5744c90e, 0x52a0a152, 0x8d6fad18, 0x67b74b6d,
0x93a089b2, 0x0f3ac5d5, 0xe5de1855, 0x43d25747, 0x4bad804a, 0x55b408d8, 0x60a36441, 0xf553e860,
0xdb2fa2c8, 0x03152b32, 0xdd27a7d5, 0x3116a8b8, 0x0a1d708c, 0xeee2f13c, 0x6acf436f, 0xce6eb4ca,
0x101cd3d9, 0x1c48a6b8, 0xe57d6f44, 0x93dcf562,
};
@ -1342,9 +1357,12 @@ void ThreadOpenConnections2(void* parg) @@ -1342,9 +1357,12 @@ void ThreadOpenConnections2(void* parg)
{
// It'll only connect to one or two seed nodes because once it connects,
// it'll get a pile of addresses with newer timestamps.
// Seed nodes are given a random 'last seen time' of between one and two
// weeks ago.
const int64 nOneWeek = 7*24*60*60;
CAddress addr;
addr.ip = pnSeed[i];
addr.nTime = 0;
addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
AddAddress(addr);
}
fSeedUsed = true;

405
src/net.h

@ -14,10 +14,9 @@ @@ -14,10 +14,9 @@
#include <arpa/inet.h>
#endif
class CMessageHeader;
class CAddress;
#include "protocol.h"
class CAddrDB;
class CInv;
class CRequestTracker;
class CNode;
class CBlockIndex;
@ -28,15 +27,7 @@ extern int nConnectTimeout; @@ -28,15 +27,7 @@ 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
{
NODE_NETWORK = (1 << 0),
};
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);
@ -54,402 +45,12 @@ bool BindListenPort(std::string& strError=REF(std::string())); @@ -54,402 +45,12 @@ bool BindListenPort(std::string& strError=REF(std::string()));
void StartNode(void* parg);
bool StopNode();
//
// Message header
// (4) message start
// (12) command
// (4) size
// (4) checksum
extern unsigned char pchMessageStart[4];
class CMessageHeader
{
public:
enum { COMMAND_SIZE=12 };
char pchMessageStart[sizeof(::pchMessageStart)];
char pchCommand[COMMAND_SIZE];
unsigned int nMessageSize;
unsigned int nChecksum;
CMessageHeader()
{
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
memset(pchCommand, 0, sizeof(pchCommand));
pchCommand[1] = 1;
nMessageSize = -1;
nChecksum = 0;
}
CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn;
nChecksum = 0;
}
IMPLEMENT_SERIALIZE
(
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(nMessageSize);
if (nVersion >= 209)
READWRITE(nChecksum);
)
std::string GetCommand()
{
if (pchCommand[COMMAND_SIZE-1] == 0)
return std::string(pchCommand, pchCommand + strlen(pchCommand));
else
return std::string(pchCommand, pchCommand + COMMAND_SIZE);
}
bool IsValid()
{
// Check start string
if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
return false;
// Check the command string for errors
for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
{
if (*p1 == 0)
{
// Must be all zeros after the first zero
for (; p1 < pchCommand + COMMAND_SIZE; p1++)
if (*p1 != 0)
return false;
}
else if (*p1 < ' ' || *p1 > 0x7E)
return false;
}
// Message size
if (nMessageSize > MAX_SIZE)
{
printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
return false;
}
return true;
}
};
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
class CAddress
{
public:
uint64 nServices;
unsigned char pchReserved[12];
unsigned int ip;
unsigned short port;
// disk and network only
unsigned int nTime;
// memory only
unsigned int nLastTry;
CAddress()
{
Init();
}
CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK)
{
Init();
ip = ipIn;
port = htons(portIn == 0 ? GetDefaultPort() : portIn);
nServices = nServicesIn;
}
explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK)
{
Init();
ip = sockaddr.sin_addr.s_addr;
port = sockaddr.sin_port;
nServices = nServicesIn;
}
explicit CAddress(const char* pszIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
{
Init();
Lookup(pszIn, *this, nServicesIn, fNameLookup, portIn);
}
explicit CAddress(const char* pszIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
{
Init();
Lookup(pszIn, *this, nServicesIn, fNameLookup, 0, true);
}
explicit CAddress(std::string strIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
{
Init();
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, portIn);
}
explicit CAddress(std::string strIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
{
Init();
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, 0, true);
}
void Init()
{
nServices = NODE_NETWORK;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = INADDR_NONE;
port = htons(GetDefaultPort());
nTime = 100000000;
nLastTry = 0;
}
IMPLEMENT_SERIALIZE
(
if (fRead)
const_cast<CAddress*>(this)->Init();
if (nType & SER_DISK)
READWRITE(nVersion);
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
READWRITE(nTime);
READWRITE(nServices);
READWRITE(FLATDATA(pchReserved)); // for IPv6
READWRITE(ip);
READWRITE(port);
)
friend inline bool operator==(const CAddress& a, const CAddress& b)
{
return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
a.ip == b.ip &&
a.port == b.port);
}
friend inline bool operator!=(const CAddress& a, const CAddress& b)
{
return (!(a == b));
}
friend inline bool operator<(const CAddress& a, const CAddress& b)
{
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
if (ret < 0)
return true;
else if (ret == 0)
{
if (ntohl(a.ip) < ntohl(b.ip))
return true;
else if (a.ip == b.ip)
return ntohs(a.port) < ntohs(b.port);
}
return false;
}
std::vector<unsigned char> GetKey() const
{
CDataStream ss;
ss.reserve(18);
ss << FLATDATA(pchReserved) << ip << port;
#if defined(_MSC_VER) && _MSC_VER < 1300
return std::vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
#else
return std::vector<unsigned char>(ss.begin(), ss.end());
#endif
}
struct sockaddr_in GetSockAddr() const
{
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = ip;
sockaddr.sin_port = port;
return sockaddr;
}
bool IsIPv4() const
{
return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
}
bool IsRFC1918() const
{
return IsIPv4() && (GetByte(3) == 10 ||
(GetByte(3) == 192 && GetByte(2) == 168) ||
(GetByte(3) == 172 &&
(GetByte(2) >= 16 && GetByte(2) <= 31)));
}
bool IsRFC3927() const
{
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
}
bool IsLocal() const
{
return IsIPv4() && (GetByte(3) == 127 ||
GetByte(3) == 0);
}
bool IsRoutable() const
{
return IsValid() &&
!(IsRFC1918() || IsRFC3927() || IsLocal());
}
bool IsValid() const
{
// Clean up 3-byte shifted addresses caused by garbage in size field
// of addr messages from versions before 0.2.9 checksum.
// Two consecutive addr messages look like this:
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
// so if the first length field is garbled, it reads the second batch
// of addr misaligned by 3 bytes.
if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
return false;
return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
}
unsigned char GetByte(int n) const
{
return ((unsigned char*)&ip)[3-n];
}
std::string ToStringIPPort() const
{
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
}
std::string ToStringIP() const
{
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
std::string ToStringPort() const
{
return strprintf("%u", ntohs(port));
}
std::string ToString() const
{
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
}
void print() const
{
printf("CAddress(%s)\n", ToString().c_str());
}
};
enum
{
MSG_TX = 1,
MSG_BLOCK,
};
static const char* ppszTypeName[] =
{
"ERROR",
"tx",
"block",
};
class CInv
{
public:
int type;
uint256 hash;
CInv()
{
type = 0;
hash = 0;
}
CInv(int typeIn, const uint256& hashIn)
{
type = typeIn;
hash = hashIn;
}
CInv(const std::string& strType, const uint256& hashIn)
{
int i;
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
{
if (strType == ppszTypeName[i])
{
type = i;
break;
}
}
if (i == ARRAYLEN(ppszTypeName))
throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
hash = hashIn;
}
IMPLEMENT_SERIALIZE
(
READWRITE(type);
READWRITE(hash);
)
friend inline bool operator<(const CInv& a, const CInv& b)
{
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}
bool IsKnownType() const
{
return (type >= 1 && type < ARRAYLEN(ppszTypeName));
}
const char* GetCommand() const
{
if (!IsKnownType())
throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
return ppszTypeName[type];
}
std::string ToString() const
{
return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str());
}
void print() const
{
printf("CInv(%s)\n", ToString().c_str());
}
};
class CRequestTracker
{
public:
@ -476,10 +77,8 @@ extern bool fClient; @@ -476,10 +77,8 @@ extern bool fClient;
extern bool fAllowDNS;
extern uint64 nLocalServices;
extern CAddress addrLocalHost;
extern CNode* pnodeLocalHost;
extern uint64 nLocalHostNonce;
extern boost::array<int, 10> vnThreadsRunning;
extern SOCKET hListenSocket;
extern std::vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;

312
src/protocol.cpp

@ -0,0 +1,312 @@ @@ -0,0 +1,312 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "protocol.h"
#include "util.h"
#ifndef __WXMSW__
# include <arpa/inet.h>
#endif
// Prototypes from net.h, but that header (currently) stinks, can't #include it without breaking things
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);
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
static const char* ppszTypeName[] =
{
"ERROR",
"tx",
"block",
};
CMessageHeader::CMessageHeader()
{
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
memset(pchCommand, 0, sizeof(pchCommand));
pchCommand[1] = 1;
nMessageSize = -1;
nChecksum = 0;
}
CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn;
nChecksum = 0;
}
std::string CMessageHeader::GetCommand() const
{
if (pchCommand[COMMAND_SIZE-1] == 0)
return std::string(pchCommand, pchCommand + strlen(pchCommand));
else
return std::string(pchCommand, pchCommand + COMMAND_SIZE);
}
bool CMessageHeader::IsValid() const
{
// Check start string
if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
return false;
// Check the command string for errors
for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
{
if (*p1 == 0)
{
// Must be all zeros after the first zero
for (; p1 < pchCommand + COMMAND_SIZE; p1++)
if (*p1 != 0)
return false;
}
else if (*p1 < ' ' || *p1 > 0x7E)
return false;
}
// Message size
if (nMessageSize > MAX_SIZE)
{
printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
return false;
}
return true;
}
CAddress::CAddress()
{
Init();
}
CAddress::CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn)
{
Init();
ip = ipIn;
port = htons(portIn == 0 ? GetDefaultPort() : portIn);
nServices = nServicesIn;
}
CAddress::CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn)
{
Init();
ip = sockaddr.sin_addr.s_addr;
port = sockaddr.sin_port;
nServices = nServicesIn;
}
CAddress::CAddress(const char* pszIn, int portIn, bool fNameLookup, uint64 nServicesIn)
{
Init();
Lookup(pszIn, *this, nServicesIn, fNameLookup, portIn);
}
CAddress::CAddress(const char* pszIn, bool fNameLookup, uint64 nServicesIn)
{
Init();
Lookup(pszIn, *this, nServicesIn, fNameLookup, 0, true);
}
CAddress::CAddress(std::string strIn, int portIn, bool fNameLookup, uint64 nServicesIn)
{
Init();
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, portIn);
}
CAddress::CAddress(std::string strIn, bool fNameLookup, uint64 nServicesIn)
{
Init();
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, 0, true);
}
void CAddress::Init()
{
nServices = NODE_NETWORK;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = INADDR_NONE;
port = htons(GetDefaultPort());
nTime = 100000000;
nLastTry = 0;
}
bool operator==(const CAddress& a, const CAddress& b)
{
return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
a.ip == b.ip &&
a.port == b.port);
}
bool operator!=(const CAddress& a, const CAddress& b)
{
return (!(a == b));
}
bool operator<(const CAddress& a, const CAddress& b)
{
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
if (ret < 0)
return true;
else if (ret == 0)
{
if (ntohl(a.ip) < ntohl(b.ip))
return true;
else if (a.ip == b.ip)
return ntohs(a.port) < ntohs(b.port);
}
return false;
}
std::vector<unsigned char> CAddress::GetKey() const
{
CDataStream ss;
ss.reserve(18);
ss << FLATDATA(pchReserved) << ip << port;
#if defined(_MSC_VER) && _MSC_VER < 1300
return std::vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
#else
return std::vector<unsigned char>(ss.begin(), ss.end());
#endif
}
struct sockaddr_in CAddress::GetSockAddr() const
{
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = ip;
sockaddr.sin_port = port;
return sockaddr;
}
bool CAddress::IsIPv4() const
{
return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
}
bool CAddress::IsRFC1918() const
{
return IsIPv4() && (GetByte(3) == 10 ||
(GetByte(3) == 192 && GetByte(2) == 168) ||
(GetByte(3) == 172 &&
(GetByte(2) >= 16 && GetByte(2) <= 31)));
}
bool CAddress::IsRFC3927() const
{
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
}
bool CAddress::IsLocal() const
{
return IsIPv4() && (GetByte(3) == 127 ||
GetByte(3) == 0);
}
bool CAddress::IsRoutable() const
{
return IsValid() &&
!(IsRFC1918() || IsRFC3927() || IsLocal());
}
bool CAddress::IsValid() const
{
// Clean up 3-byte shifted addresses caused by garbage in size field
// of addr messages from versions before 0.2.9 checksum.
// Two consecutive addr messages look like this:
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
// so if the first length field is garbled, it reads the second batch
// of addr misaligned by 3 bytes.
if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
return false;
return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
}
unsigned char CAddress::GetByte(int n) const
{
return ((unsigned char*)&ip)[3-n];
}
std::string CAddress::ToStringIPPort() const
{
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
}
std::string CAddress::ToStringIP() const
{
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
std::string CAddress::ToStringPort() const
{
return strprintf("%u", ntohs(port));
}
std::string CAddress::ToString() const
{
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
}
void CAddress::print() const
{
printf("CAddress(%s)\n", ToString().c_str());
}
CInv::CInv()
{
type = 0;
hash = 0;
}
CInv::CInv(int typeIn, const uint256& hashIn)
{
type = typeIn;
hash = hashIn;
}
CInv::CInv(const std::string& strType, const uint256& hashIn)
{
int i;
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
{
if (strType == ppszTypeName[i])
{
type = i;
break;
}
}
if (i == ARRAYLEN(ppszTypeName))
throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
hash = hashIn;
}
bool operator<(const CInv& a, const CInv& b)
{
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}
bool CInv::IsKnownType() const
{
return (type >= 1 && type < ARRAYLEN(ppszTypeName));
}
const char* CInv::GetCommand() const
{
if (!IsKnownType())
throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
return ppszTypeName[type];
}
std::string CInv::ToString() const
{
return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str());
}
void CInv::print() const
{
printf("CInv(%s)\n", ToString().c_str());
}

150
src/protocol.h

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2011 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#ifndef __cplusplus
# error This header can only be compiled as C++.
#endif
#ifndef __INCLUDED_PROTOCOL_H__
#define __INCLUDED_PROTOCOL_H__
#include "serialize.h"
#include <string>
#include "uint256.h"
extern bool fTestNet;
static inline unsigned short GetDefaultPort(const bool testnet = fTestNet)
{
return testnet ? 18333 : 8333;
}
//
// Message header
// (4) message start
// (12) command
// (4) size
// (4) checksum
extern unsigned char pchMessageStart[4];
class CMessageHeader
{
public:
CMessageHeader();
CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn);
std::string GetCommand() const;
bool IsValid() const;
IMPLEMENT_SERIALIZE
(
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(nMessageSize);
if (nVersion >= 209)
READWRITE(nChecksum);
)
// TODO: make private (improves encapsulation)
public:
enum { COMMAND_SIZE=12 };
char pchMessageStart[sizeof(::pchMessageStart)];
char pchCommand[COMMAND_SIZE];
unsigned int nMessageSize;
unsigned int nChecksum;
};
enum
{
NODE_NETWORK = (1 << 0),
};
class CAddress
{
public:
CAddress();
CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK);
explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK);
explicit CAddress(const char* pszIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
explicit CAddress(const char* pszIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
explicit CAddress(std::string strIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
explicit CAddress(std::string strIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
void Init();
IMPLEMENT_SERIALIZE
(
if (fRead)
const_cast<CAddress*>(this)->Init();
if (nType & SER_DISK)
READWRITE(nVersion);
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
READWRITE(nTime);
READWRITE(nServices);
READWRITE(FLATDATA(pchReserved)); // for IPv6
READWRITE(ip);
READWRITE(port);
)
friend bool operator==(const CAddress& a, const CAddress& b);
friend bool operator!=(const CAddress& a, const CAddress& b);
friend bool operator<(const CAddress& a, const CAddress& b);
std::vector<unsigned char> GetKey() const;
struct sockaddr_in GetSockAddr() const;
bool IsIPv4() const;
bool IsRFC1918() const;
bool IsRFC3927() const;
bool IsLocal() const;
bool IsRoutable() const;
bool IsValid() const;
unsigned char GetByte(int n) const;
std::string ToStringIPPort() const;
std::string ToStringIP() const;
std::string ToStringPort() const;
std::string ToString() const;
void print() const;
// TODO: make private (improves encapsulation)
public:
uint64 nServices;
unsigned char pchReserved[12];
unsigned int ip;
unsigned short port;
// disk and network only
unsigned int nTime;
// memory only
unsigned int nLastTry;
};
class CInv
{
public:
CInv();
CInv(int typeIn, const uint256& hashIn);
CInv(const std::string& strType, const uint256& hashIn);
IMPLEMENT_SERIALIZE
(
READWRITE(type);
READWRITE(hash);
)
friend bool operator<(const CInv& a, const CInv& b);
bool IsKnownType() const;
const char* GetCommand() const;
std::string ToString() const;
void print() const;
// TODO: make private (improves encapsulation)
public:
int type;
uint256 hash;
};
#endif // __INCLUDED_PROTOCOL_H__

102
src/script.cpp

@ -1033,48 +1033,45 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash @@ -1033,48 +1033,45 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
return false;
// Compile solution
CRITICAL_BLOCK(keystore.cs_KeyStore)
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
if (item.first == OP_PUBKEY)
{
if (item.first == OP_PUBKEY)
// Sign
const valtype& vchPubKey = item.second;
CKey key;
if (!keystore.GetKey(Hash160(vchPubKey), key))
return false;
if (key.GetPubKey() != vchPubKey)
return false;
if (hash != 0)
{
// Sign
const valtype& vchPubKey = item.second;
CKey key;
if (!keystore.GetKey(Hash160(vchPubKey), key))
return false;
if (key.GetPubKey() != vchPubKey)
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;
}
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig;
}
else if (item.first == OP_PUBKEYHASH)
}
else if (item.first == OP_PUBKEYHASH)
{
// Sign and give pubkey
CKey key;
if (!keystore.GetKey(uint160(item.second), key))
return false;
if (hash != 0)
{
// Sign and give pubkey
CKey key;
if (!keystore.GetKey(uint160(item.second), key))
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
if (hash != 0)
{
vector<unsigned char> vchSig;
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << key.GetPubKey();
}
}
else
{
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << key.GetPubKey();
}
}
else
{
return false;
}
}
return true;
@ -1095,35 +1092,31 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) @@ -1095,35 +1092,31 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
return false;
// Compile solution
CRITICAL_BLOCK(keystore.cs_KeyStore)
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
if (item.first == OP_PUBKEY)
{
if (item.first == OP_PUBKEY)
{
const valtype& vchPubKey = item.second;
vector<unsigned char> vchPubKeyFound;
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
return false;
if (vchPubKeyFound != vchPubKey)
return false;
}
else if (item.first == OP_PUBKEYHASH)
{
if (!keystore.HaveKey(uint160(item.second)))
return false;
}
else
{
const valtype& vchPubKey = item.second;
vector<unsigned char> vchPubKeyFound;
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
return false;
}
if (vchPubKeyFound != vchPubKey)
return false;
}
else if (item.first == OP_PUBKEYHASH)
{
if (!keystore.HaveKey(uint160(item.second)))
return false;
}
else
{
return false;
}
}
return true;
}
// requires either keystore==0, or a lock on keystore->cs_KeyStore
bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
{
vector<pair<opcodetype, valtype> > vSolution;
@ -1147,8 +1140,7 @@ bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* ke @@ -1147,8 +1140,7 @@ bool static ExtractAddressInner(const CScript& scriptPubKey, const CKeyStore* ke
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
{
if (keystore)
CRITICAL_BLOCK(keystore->cs_KeyStore)
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
return ExtractAddressInner(scriptPubKey, keystore, addressRet);
else
return ExtractAddressInner(scriptPubKey, NULL, addressRet);
return false;

11
src/serialize.h

@ -64,10 +64,13 @@ static const int VERSION = 32500; @@ -64,10 +64,13 @@ static const int VERSION = 32500;
static const char* pszSubVer = "";
static const bool VERSION_IS_BETA = true;
// Used to bypass the rule against non-const reference to temporary
// where it makes sense with wrappers such as CFlatData or CTxDB
template<typename T>
inline T& REF(const T& val)
{
return const_cast<T&>(val);
}
/////////////////////////////////////////////////////////////////
//

381
src/ui.cpp

@ -708,7 +708,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -708,7 +708,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address))
{
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
//strDescription += _("Received payment to ");
//strDescription += _("Received with address ");
@ -792,7 +792,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -792,7 +792,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
}
string strDescription = _("To: ");
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
if (pwalletMain->mapAddressBook.count(address) && !pwalletMain->mapAddressBook[address].empty())
strDescription += pwalletMain->mapAddressBook[address] + " ";
strDescription += strAddress;
@ -862,7 +862,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event) @@ -862,7 +862,7 @@ 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(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
printf("RefreshListCtrl starting\n");
fEntered = true;
@ -890,7 +890,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event) @@ -890,7 +890,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
if (fShutdown)
return;
bool fEntered = false;
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
fEntered = true;
uint256& hash = vSorted[i++].second;
@ -913,7 +913,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event) @@ -913,7 +913,7 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
static int64 nLastTime;
if (GetTime() > nLastTime + 30)
{
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
nLastTime = GetTime();
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
@ -937,7 +937,7 @@ void CMainFrame::RefreshStatusColumn() @@ -937,7 +937,7 @@ void CMainFrame::RefreshStatusColumn()
if (nTop == nLastTop && pindexLastBest == pindexBest)
return;
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
int nStart = nTop;
int nEnd = min(nStart + 100, m_listCtrl->GetItemCount());
@ -1057,7 +1057,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) @@ -1057,7 +1057,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
// Update listctrl contents
if (!pwalletMain->vWalletUpdated.empty())
{
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
string strTop;
if (m_listCtrl->GetItemCount())
@ -1075,7 +1075,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) @@ -1075,7 +1075,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
}
// Balance total
TRY_CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
TRY_CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
fPaintedBalance = true;
m_staticTextBalance->SetLabel(FormatMoney(pwalletMain->GetBalance()) + " ");
@ -1247,83 +1247,80 @@ void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event) @@ -1247,83 +1247,80 @@ void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event)
strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
_("Passphrase")).ToStdString();
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
bool fWasLocked = pwalletMain->IsLocked();
pwalletMain->Lock();
bool fWasLocked = pwalletMain->IsLocked();
pwalletMain->Lock();
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (fWasLocked)
pwalletMain->Lock();
if (fWasLocked)
pwalletMain->Lock();
string strNewWalletPass;
strNewWalletPass.reserve(100);
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
string strNewWalletPass;
strNewWalletPass.reserve(100);
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
// obtain new wallet encrypt/decrypt key, from passphrase
// Note that the passphrase is not mlock()d during this entry and could potentially
// be obtained from disk long after bitcoin has run.
strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
_("Passphrase")).ToStdString();
// obtain new wallet encrypt/decrypt key, from passphrase
// Note that the passphrase is not mlock()d during this entry and could potentially
// be obtained from disk long after bitcoin has run.
strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."),
_("Passphrase")).ToStdString();
if (!strNewWalletPass.size())
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (!strNewWalletPass.size())
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
string strNewWalletPassTest;
strNewWalletPassTest.reserve(100);
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
string strNewWalletPassTest;
strNewWalletPassTest.reserve(100);
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
// obtain new wallet encrypt/decrypt key, from passphrase
// Note that the passphrase is not mlock()d during this entry and could potentially
// be obtained from disk long after bitcoin has run.
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
_("Passphrase")).ToStdString();
// obtain new wallet encrypt/decrypt key, from passphrase
// Note that the passphrase is not mlock()d during this entry and could potentially
// be obtained from disk long after bitcoin has run.
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
_("Passphrase")).ToStdString();
if (strNewWalletPassTest != strNewWalletPass)
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (strNewWalletPassTest != strNewWalletPass)
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
{
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
return;
}
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
}
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
@ -1387,21 +1384,21 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event) @@ -1387,21 +1384,21 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
string strName = dialog.GetValue();
string strAddress;
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
// Generate new key
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
if (fWasLocked)
pwalletMain->Lock();
}
// Generate new key
std::vector<unsigned char> newKey;
pwalletMain->GetKeyFromPool(newKey, true);
strAddress = CBitcoinAddress(newKey).ToString();
if (fWasLocked)
pwalletMain->Lock();
// Save
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
pwalletMain->SetAddressBookName(strAddress, strName);
SetDefaultReceivingAddress(strAddress);
}
@ -1420,7 +1417,7 @@ void CMainFrame::OnListItemActivated(wxListEvent& event) @@ -1420,7 +1417,7 @@ void CMainFrame::OnListItemActivated(wxListEvent& event)
{
uint256 hash((string)GetItemText(m_listCtrl, event.GetIndex(), 1));
CWalletTx wtx;
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
if (mi == pwalletMain->mapWallet.end())
@ -1451,7 +1448,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails @@ -1451,7 +1448,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
#ifdef __WXMSW__
SetSize(nScaleX * GetSize().GetWidth(), nScaleY * GetSize().GetHeight());
#endif
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
string strHTML;
strHTML.reserve(4000);
@ -1662,7 +1659,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails @@ -1662,7 +1659,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
strHTML += HtmlEscape(wtx.ToString(), true);
strHTML += "<br><b>Inputs:</b><br>";
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
@ -2160,38 +2157,42 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) @@ -2160,38 +2157,42 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
if (fBitcoinAddress)
{
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
string strError;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
// Send to bitcoin address
CScript scriptPubKey;
scriptPubKey.SetBitcoinAddress(address);
string strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
if (strError == "")
wxMessageBox(_("Payment sent "), _("Sending..."));
else if (strError == "ABORTED")
{
if (fWasLocked)
pwalletMain->Lock();
return; // leave send dialog open
}
else
{
wxMessageBox(strError + " ", _("Sending..."));
EndModal(false);
if (fWasLocked)
pwalletMain->Lock();
return;
}
strError = pwalletMain->SendMoney(scriptPubKey, nValue, wtx, true);
}
if (strError == "")
{
pframeMain->RefreshListCtrl();
wxMessageBox(_("Payment sent "), _("Sending..."));
}
else if (strError == "ABORTED")
{
if (fWasLocked)
pwalletMain->Lock();
return; // leave send dialog open
}
else
{
wxMessageBox(strError + " ", _("Sending..."));
EndModal(false);
if (fWasLocked)
pwalletMain->Lock();
}
return;
}
if (fWasLocked)
pwalletMain->Lock();
}
else
{
@ -2212,7 +2213,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) @@ -2212,7 +2213,7 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
return;
}
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
if (!pwalletMain->mapAddressBook.count(address))
pwalletMain->SetAddressBookName(strAddress, "");
@ -2464,83 +2465,89 @@ void CSendingDialog::OnReply2(CDataStream& vRecv) @@ -2464,83 +2465,89 @@ void CSendingDialog::OnReply2(CDataStream& vRecv)
return;
}
CRITICAL_BLOCK(cs_main)
// Pay
if (!Status(_("Creating transaction...")))
return;
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
{
// Pay
if (!Status(_("Creating transaction...")))
return;
if (nPrice + nTransactionFee > pwalletMain->GetBalance())
{
Error(_("Insufficient funds"));
return;
}
Error(_("Insufficient funds"));
return;
}
CReserveKey reservekey(pwalletMain);
int64 nFeeRequired;
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
CReserveKey reservekey(pwalletMain);
int64 nFeeRequired;
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired))
{
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
else
Error(_("Transaction creation failed"));
return;
}
bool fTxCreated = false;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
fTxCreated = pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired);
}
if (!fTxCreated)
{
if (nPrice + nFeeRequired > pwalletMain->GetBalance())
Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str()));
else
Error(_("Transaction creation failed"));
return;
}
if (fWasLocked)
pwalletMain->Lock();
}
if (fWasLocked)
pwalletMain->Lock();
// Transaction fee
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
{
Error(_("Transaction aborted"));
return;
}
// Transaction fee
if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this))
{
Error(_("Transaction aborted"));
return;
}
// Make sure we're still connected
CNode* pnode = ConnectNode(addr, 2 * 60 * 60);
if (!pnode)
{
Error(_("Lost connection, transaction cancelled"));
return;
}
// Make sure we're still connected
CNode* pnode = ConnectNode(addr, 2 * 60 * 60);
if (!pnode)
{
Error(_("Lost connection, transaction cancelled"));
return;
}
// Last chance to cancel
Sleep(50);
// Last chance to cancel
Sleep(50);
if (!Status())
return;
fCanCancel = false;
if (fAbort)
{
fCanCancel = true;
if (!Status())
return;
fCanCancel = false;
if (fAbort)
{
fCanCancel = true;
if (!Status())
return;
fCanCancel = false;
}
if (!Status(_("Sending payment...")))
return;
}
if (!Status(_("Sending payment...")))
return;
// Commit
if (!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;
}
// Commit
bool fTxCommitted = false;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
fTxCommitted = pwalletMain->CommitTransaction(wtx, reservekey);
}
if (!fTxCommitted)
{
Error(_("The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."));
return;
}
// Send payment tx to seller, with response going to OnReply3 via event handler
CWalletTx wtxSend = wtx;
wtxSend.fFromMe = false;
pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this);
// Send payment tx to seller, with response going to OnReply3 via event handler
CWalletTx wtxSend = wtx;
wtxSend.fFromMe = false;
pnode->PushRequest("submitorder", wtxSend, SendingDialogOnReply3, this);
Status(_("Waiting for confirmation..."));
MainFrameRepaint();
}
Status(_("Waiting for confirmation..."));
MainFrameRepaint();
}
void SendingDialogOnReply3(void* parg, CDataStream& vRecv)
@ -2621,8 +2628,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit @@ -2621,8 +2628,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
m_listCtrlReceiving->SetFocus();
// Fill listctrl with address book data
CRITICAL_BLOCK(pwalletMain->cs_KeyStore)
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue();
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
@ -2683,7 +2689,7 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event) @@ -2683,7 +2689,7 @@ void CAddressBookDialog::OnListEndLabelEdit(wxListEvent& event)
if (event.IsEditCancelled())
return;
string strAddress = (string)GetItemText(m_listCtrl, event.GetIndex(), 1);
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
pwalletMain->SetAddressBookName(strAddress, string(event.GetText()));
pframeMain->RefreshListCtrl();
}
@ -2719,7 +2725,7 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event) @@ -2719,7 +2725,7 @@ void CAddressBookDialog::OnButtonDelete(wxCommandEvent& event)
if (m_listCtrl->GetItemState(nIndex, wxLIST_STATE_SELECTED))
{
string strAddress = (string)GetItemText(m_listCtrl, nIndex, 1);
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
pwalletMain->DelAddressBookName(strAddress);
m_listCtrl->DeleteItem(nIndex);
}
@ -2779,7 +2785,7 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event) @@ -2779,7 +2785,7 @@ void CAddressBookDialog::OnButtonEdit(wxCommandEvent& event)
}
// Write back
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
{
if (strAddress != strAddressOrg)
pwalletMain->DelAddressBookName(strAddressOrg);
@ -2819,22 +2825,21 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event) @@ -2819,22 +2825,21 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
return;
strName = dialog.GetValue();
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
{
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
bool fWasLocked = pwalletMain->IsLocked();
if (!GetWalletPassphrase())
return;
// Generate new key
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
// Generate new key
std::vector<unsigned char> newKey;
pwalletMain->GetKeyFromPool(newKey, true);
strAddress = CBitcoinAddress(newKey).ToString();
if (fWasLocked)
pwalletMain->Lock();
}
if (fWasLocked)
pwalletMain->Lock();
}
// Add to list and select it
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
CRITICAL_BLOCK(pwalletMain->cs_wallet)
pwalletMain->SetAddressBookName(strAddress, strName);
int nIndex = InsertLine(m_listCtrl, strName, strAddress);
SetSelection(m_listCtrl, nIndex);

8
src/util.cpp

@ -940,17 +940,21 @@ static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lock @@ -940,17 +940,21 @@ static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lock
static boost::thread_specific_ptr<LockStack> lockstack;
static void potential_deadlock_detected(const LockStack& s1, const LockStack& s2)
static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
{
printf("POTENTIAL DEADLOCK DETECTED\n");
printf("Previous lock order was:\n");
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
{
if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)");
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
}
printf("Current lock order is:\n");
BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
{
if (i.first == mismatch.first) printf(" (1)");
if (i.first == mismatch.second) printf(" (2)");
printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine);
}
}
@ -977,7 +981,7 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) @@ -977,7 +981,7 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
if (lockorders.count(p2))
{
potential_deadlock_detected(lockorders[p2], lockorders[p1]);
potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
break;
}
}

8
src/util.h

@ -67,14 +67,6 @@ typedef unsigned long long uint64; @@ -67,14 +67,6 @@ typedef unsigned long long uint64;
// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
#define PAIRTYPE(t1, t2) std::pair<t1, t2>
// Used to bypass the rule against non-const reference to temporary
// where it makes sense with wrappers such as CFlatData or CTxDB
template<typename T>
inline T& REF(const T& val)
{
return (T&)val;
}
// Align by increasing pointer, must have extra space at end of buffer
template <size_t nBytes, typename T>
T* alignup(T* p)

239
src/wallet.cpp

@ -33,7 +33,7 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector @@ -33,7 +33,7 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
return false;
if (!fFileBacked)
return true;
CRITICAL_BLOCK(cs_pwalletdbEncryption)
CRITICAL_BLOCK(cs_wallet)
{
if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
@ -44,14 +44,13 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector @@ -44,14 +44,13 @@ bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector
bool CWallet::Unlock(const string& strWalletPassphrase)
{
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!IsLocked())
return false;
if (!IsLocked())
return false;
CCrypter crypter;
CKeyingMaterial vMasterKey;
CCrypter crypter;
CKeyingMaterial vMasterKey;
CRITICAL_BLOCK(cs_wallet)
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
{
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
@ -61,16 +60,15 @@ bool CWallet::Unlock(const string& strWalletPassphrase) @@ -61,16 +60,15 @@ bool CWallet::Unlock(const string& strWalletPassphrase)
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
}
return false;
}
bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const string& strNewWalletPassphrase)
{
CRITICAL_BLOCK(cs_vMasterKey)
{
bool fWasLocked = IsLocked();
bool fWasLocked = IsLocked();
CRITICAL_BLOCK(cs_wallet)
{
Lock();
CCrypter crypter;
@ -79,7 +77,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const @@ -79,7 +77,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const
{
if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if(!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
return false;
if (CCryptoKeyStore::Unlock(vMasterKey))
{
@ -107,6 +105,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const @@ -107,6 +105,7 @@ bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const
}
}
}
return false;
}
@ -125,44 +124,42 @@ public: @@ -125,44 +124,42 @@ public:
bool CWallet::EncryptWallet(const string& strWalletPassphrase)
{
CRITICAL_BLOCK(cs_KeyStore)
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_pwalletdbEncryption)
{
if (IsCrypted())
return false;
if (IsCrypted())
return false;
CKeyingMaterial vMasterKey;
RandAddSeedPerfmon();
CKeyingMaterial vMasterKey;
RandAddSeedPerfmon();
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
CMasterKey kMasterKey;
CMasterKey kMasterKey;
RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
CCrypter crypter;
int64 nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
CCrypter crypter;
int64 nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
nStartTime = GetTimeMillis();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false;
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
return false;
if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
return false;
CRITICAL_BLOCK(cs_wallet)
{
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
if (fFileBacked)
{
@ -191,6 +188,7 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase) @@ -191,6 +188,7 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase)
Lock();
}
return true;
}
@ -199,7 +197,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx) @@ -199,7 +197,7 @@ 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)
CRITICAL_BLOCK(cs_wallet)
{
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
@ -222,7 +220,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx) @@ -222,7 +220,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx)
bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
// 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));
@ -270,8 +268,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) @@ -270,8 +268,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{
if (txout.scriptPubKey == scriptDefaultKey)
{
SetDefaultKey(GetOrReuseKeyFromPool());
SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
std::vector<unsigned char> newDefaultKey;
if (GetKeyFromPool(newDefaultKey, false))
{
SetDefaultKey(newDefaultKey);
SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
}
}
}
#endif
@ -290,18 +292,21 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) @@ -290,18 +292,21 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
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))
CRITICAL_BLOCK(cs_wallet)
{
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
if (pblock)
wtx.SetMerkleBranch(pblock);
return AddToWallet(wtx);
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);
}
else
WalletUpdateSpent(tx);
return false;
}
@ -309,7 +314,7 @@ bool CWallet::EraseFromWallet(uint256 hash) @@ -309,7 +314,7 @@ bool CWallet::EraseFromWallet(uint256 hash)
{
if (!fFileBacked)
return false;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(hash);
@ -320,7 +325,7 @@ bool CWallet::EraseFromWallet(uint256 hash) @@ -320,7 +325,7 @@ bool CWallet::EraseFromWallet(uint256 hash)
bool CWallet::IsMine(const CTxIn &txin) const
{
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
@ -336,7 +341,7 @@ bool CWallet::IsMine(const CTxIn &txin) const @@ -336,7 +341,7 @@ bool CWallet::IsMine(const CTxIn &txin) const
int64 CWallet::GetDebit(const CTxIn &txin) const
{
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
@ -352,19 +357,6 @@ int64 CWallet::GetDebit(const CTxIn &txin) const @@ -352,19 +357,6 @@ int64 CWallet::GetDebit(const CTxIn &txin) const
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;
}
@ -372,7 +364,7 @@ int CWalletTx::GetRequestCount() const @@ -372,7 +364,7 @@ int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
CRITICAL_BLOCK(pwallet->cs_mapRequestCount)
CRITICAL_BLOCK(pwallet->cs_wallet)
{
if (IsCoinBase())
{
@ -478,7 +470,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i @@ -478,7 +470,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, i
nSent += s.second;
nFee = allFee;
}
CRITICAL_BLOCK(pwallet->cs_mapAddressBook)
CRITICAL_BLOCK(pwallet->cs_wallet)
{
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
{
@ -508,7 +500,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) @@ -508,7 +500,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
vWorkQueue.push_back(txin.prevout.hash);
// This critsect is OK because txdb is already open
CRITICAL_BLOCK(pwallet->cs_mapWallet)
CRITICAL_BLOCK(pwallet->cs_wallet)
{
map<uint256, const CMerkleTx*> mapWalletPrev;
set<uint256> setAlreadyDone;
@ -564,7 +556,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) @@ -564,7 +556,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
int ret = 0;
CBlockIndex* pindex = pindexStart;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
while (pindex)
{
@ -585,7 +577,7 @@ void CWallet::ReacceptWalletTransactions() @@ -585,7 +577,7 @@ void CWallet::ReacceptWalletTransactions()
{
CTxDB txdb("r");
bool fRepeat = true;
while (fRepeat) CRITICAL_BLOCK(cs_mapWallet)
while (fRepeat) CRITICAL_BLOCK(cs_wallet)
{
fRepeat = false;
vector<CDiskTxPos> vMissingTx;
@ -688,7 +680,7 @@ void CWallet::ResendWalletTransactions() @@ -688,7 +680,7 @@ void CWallet::ResendWalletTransactions()
// Rebroadcast any of our txes that aren't in a block yet
printf("ResendWalletTransactions()\n");
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
// Sort them in chronological order
multimap<unsigned int, CWalletTx*> mapSorted;
@ -722,7 +714,7 @@ void CWallet::ResendWalletTransactions() @@ -722,7 +714,7 @@ void CWallet::ResendWalletTransactions()
int64 CWallet::GetBalance() const
{
int64 nTotal = 0;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
@ -764,7 +756,7 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe @@ -764,7 +756,7 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe
vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
int64 nTotalLower = 0;
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
vector<const CWalletTx*> vCoins;
vCoins.reserve(mapWallet.size());
@ -922,10 +914,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW @@ -922,10 +914,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
wtxNew.pwallet = this;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{
// txdb must be opened before the mapWallet lock
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
{
nFeeRet = nTransactionFee;
loop
@ -1036,9 +1028,9 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w @@ -1036,9 +1028,9 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{
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
@ -1068,8 +1060,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) @@ -1068,8 +1060,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
}
// Track how many getdata requests our transaction gets
CRITICAL_BLOCK(cs_mapRequestCount)
mapRequestCount[wtxNew.GetHash()] = 0;
mapRequestCount[wtxNew.GetHash()] = 0;
// Broadcast
if (!wtxNew.AcceptToMemoryPool())
@ -1087,29 +1078,26 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) @@ -1087,29 +1078,26 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
// requires cs_main lock
string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
CReserveKey reservekey(this);
int64 nFeeRequired;
CRITICAL_BLOCK(cs_vMasterKey)
if (IsLocked())
{
if (IsLocked())
{
string strError = _("Error: Wallet locked, unable to create transaction ");
printf("SendMoney() : %s", strError.c_str());
return strError;
}
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;
}
string strError = _("Error: Wallet locked, unable to create transaction ");
printf("SendMoney() : %s", strError.c_str());
return strError;
}
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))
@ -1124,7 +1112,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, @@ -1124,7 +1112,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
// requires cs_main lock
string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
// Check amount
@ -1158,7 +1145,10 @@ int CWallet::LoadWallet(bool& fFirstRunRet) @@ -1158,7 +1145,10 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
// Create new keyUser and set as default key
RandAddSeedPerfmon();
SetDefaultKey(GetOrReuseKeyFromPool());
std::vector<unsigned char> newDefaultKey;
if (!GetKeyFromPool(newDefaultKey, false))
return DB_LOAD_FAIL;
SetDefaultKey(newDefaultKey);
if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
return DB_LOAD_FAIL;
}
@ -1187,7 +1177,7 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address) @@ -1187,7 +1177,7 @@ bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
void CWallet::PrintWallet(const CBlock& block)
{
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
if (mapWallet.count(block.vtx[0].GetHash()))
{
@ -1200,7 +1190,7 @@ void CWallet::PrintWallet(const CBlock& block) @@ -1200,7 +1190,7 @@ void CWallet::PrintWallet(const CBlock& block)
bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
{
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
if (mi != mapWallet.end())
@ -1233,10 +1223,7 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut) @@ -1233,10 +1223,7 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
bool CWallet::TopUpKeyPool()
{
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_setKeyPool)
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_wallet)
{
if (IsLocked())
return false;
@ -1263,9 +1250,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool) @@ -1263,9 +1250,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
{
nIndex = -1;
keypool.vchPubKey.clear();
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_setKeyPool)
CRITICAL_BLOCK(cs_wallet)
{
if (!IsLocked())
TopUpKeyPool();
@ -1293,10 +1278,7 @@ void CWallet::KeepKey(int64 nIndex) @@ -1293,10 +1278,7 @@ void CWallet::KeepKey(int64 nIndex)
if (fFileBacked)
{
CWalletDB walletdb(strWalletFile);
CRITICAL_BLOCK(cs_main)
{
walletdb.ErasePool(nIndex);
}
walletdb.ErasePool(nIndex);
}
printf("keypool keep %"PRI64d"\n", nIndex);
}
@ -1304,20 +1286,33 @@ void CWallet::KeepKey(int64 nIndex) @@ -1304,20 +1286,33 @@ void CWallet::KeepKey(int64 nIndex)
void CWallet::ReturnKey(int64 nIndex)
{
// Return to key pool
CRITICAL_BLOCK(cs_setKeyPool)
CRITICAL_BLOCK(cs_wallet)
setKeyPool.insert(nIndex);
printf("keypool return %"PRI64d"\n", nIndex);
}
vector<unsigned char> CWallet::GetOrReuseKeyFromPool()
bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
{
int64 nIndex = 0;
CKeyPool keypool;
ReserveKeyFromKeyPool(nIndex, keypool);
if(nIndex == -1)
return vchDefaultKey;
KeepKey(nIndex);
return keypool.vchPubKey;
CRITICAL_BLOCK(cs_wallet)
{
ReserveKeyFromKeyPool(nIndex, keypool);
if (nIndex == -1)
{
if (fAllowReuse && !vchDefaultKey.empty())
{
result = vchDefaultKey;
return true;
}
if (IsLocked()) return false;
result = GenerateNewKey();
return true;
}
KeepKey(nIndex);
result = keypool.vchPubKey;
}
return true;
}
int64 CWallet::GetOldestKeyPoolTime()

17
src/wallet.h

@ -20,14 +20,14 @@ private: @@ -20,14 +20,14 @@ private:
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
CWalletDB *pwalletdbEncryption;
CCriticalSection cs_pwalletdbEncryption;
public:
mutable CCriticalSection cs_wallet;
bool fFileBacked;
std::string strWalletFile;
std::set<int64> setKeyPool;
CCriticalSection cs_setKeyPool;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
@ -47,15 +47,12 @@ public: @@ -47,15 +47,12 @@ public:
pwalletdbEncryption = NULL;
}
mutable CCriticalSection cs_mapWallet;
std::map<uint256, CWalletTx> mapWallet;
std::vector<uint256> vWalletUpdated;
std::map<uint256, int> mapRequestCount;
mutable CCriticalSection cs_mapRequestCount;
std::map<CBitcoinAddress, std::string> mapAddressBook;
mutable CCriticalSection cs_mapAddressBook;
std::vector<unsigned char> vchDefaultKey;
@ -89,7 +86,7 @@ public: @@ -89,7 +86,7 @@ public:
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
void KeepKey(int64 nIndex);
void ReturnKey(int64 nIndex);
std::vector<unsigned char> GetOrReuseKeyFromPool();
bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
int64 GetOldestKeyPoolTime();
bool IsMine(const CTxIn& txin) const;
@ -108,7 +105,7 @@ public: @@ -108,7 +105,7 @@ public:
{
CBitcoinAddress address;
if (ExtractAddress(txout.scriptPubKey, this, address))
CRITICAL_BLOCK(cs_mapAddressBook)
CRITICAL_BLOCK(cs_wallet)
if (!mapAddressBook.count(address))
return true;
return false;
@ -172,15 +169,13 @@ public: @@ -172,15 +169,13 @@ public:
int LoadWallet(bool& fFirstRunRet);
// bool BackupWallet(const std::string& strDest);
// requires cs_mapAddressBook lock
bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
// requires cs_mapAddressBook lock
bool DelAddressBookName(const CBitcoinAddress& address);
void UpdatedTransaction(const uint256 &hashTx)
{
CRITICAL_BLOCK(cs_mapWallet)
CRITICAL_BLOCK(cs_wallet)
vWalletUpdated.push_back(hashTx);
}
@ -188,7 +183,7 @@ public: @@ -188,7 +183,7 @@ public:
void Inventory(const uint256 &hash)
{
CRITICAL_BLOCK(cs_mapRequestCount)
CRITICAL_BLOCK(cs_wallet)
{
std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
if (mi != mapRequestCount.end())

Loading…
Cancel
Save