mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-10 23:07:52 +00:00
Merge branch 'master' of https://github.com/bitcoin/bitcoin
Conflicts: src/main.cpp
This commit is contained in:
commit
7a15d4ff67
38
contrib/boost-win32.yml
Normal file
38
contrib/boost-win32.yml
Normal file
@ -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
|
@ -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: |
|
||||
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: |
|
||||
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
|
||||
|
@ -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: |
|
||||
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
Normal file
6
contrib/pyminer/README
Normal file
@ -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
Normal file
32
contrib/pyminer/example-config.cfg
Normal file
@ -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
Executable file
252
contrib/pyminer/pyminer.py
Executable file
@ -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'])
|
||||
|
@ -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.
|
@ -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;
|
@ -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
Normal file
40
contrib/wxwidgets-win32.yml
Normal file
@ -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
Normal file
42
contrib/wxwidgets.yml
Normal file
@ -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
48
doc/README
@ -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
|
||||
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
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
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.
|
||||
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
|
||||
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
|
||||
-------
|
||||
|
@ -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
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
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%.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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]);
|
||||
|
||||
// Generate a new key that is added to wallet
|
||||
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
|
||||
if (!pwalletMain->IsLocked())
|
||||
pwalletMain->TopUpKeyPool();
|
||||
|
||||
// This could be done in the same main CS as GetKeyFromKeyPool.
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
|
||||
pwalletMain->SetAddressBookName(address, strAccount);
|
||||
// Generate a new key that is added to wallet
|
||||
std::vector<unsigned char> newKey;
|
||||
if (!pwalletMain->GetKeyFromPool(newKey, false))
|
||||
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
CBitcoinAddress address(newKey);
|
||||
|
||||
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);
|
||||
|
||||
bool bKeyUsed = false;
|
||||
|
||||
// Check if the current key has been used
|
||||
if (!account.vchPubKey.empty())
|
||||
{
|
||||
walletdb.ReadAccount(strAccount, account);
|
||||
|
||||
bool bKeyUsed = false;
|
||||
|
||||
// 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)
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
|
||||
// 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)
|
||||
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)
|
||||
|
||||
// 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)
|
||||
|
||||
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)
|
||||
|
||||
// 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)
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (!wtx.IsFinal())
|
||||
continue;
|
||||
|
||||
int64 nGenerated, nReceived, nSent, nFee;
|
||||
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
|
||||
int64 nGenerated, nReceived, nSent, nFee;
|
||||
wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
|
||||
|
||||
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nBalance += nReceived;
|
||||
nBalance += nGenerated - 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)
|
||||
if (params.size() > 4)
|
||||
strComment = params[4].get_str();
|
||||
|
||||
CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
|
||||
{
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
walletdb.TxnBegin();
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
walletdb.TxnBegin();
|
||||
|
||||
int64 nNow = GetAdjustedTime();
|
||||
int64 nNow = GetAdjustedTime();
|
||||
|
||||
// Debit
|
||||
CAccountingEntry debit;
|
||||
debit.strAccount = strFrom;
|
||||
debit.nCreditDebit = -nAmount;
|
||||
debit.nTime = nNow;
|
||||
debit.strOtherAccount = strTo;
|
||||
debit.strComment = strComment;
|
||||
walletdb.WriteAccountingEntry(debit);
|
||||
// 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);
|
||||
// Credit
|
||||
CAccountingEntry credit;
|
||||
credit.strAccount = strTo;
|
||||
credit.nCreditDebit = nAmount;
|
||||
credit.nTime = nNow;
|
||||
credit.strOtherAccount = strFrom;
|
||||
credit.strComment = strComment;
|
||||
walletdb.WriteAccountingEntry(credit);
|
||||
|
||||
walletdb.TxnCommit();
|
||||
|
||||
walletdb.TxnCommit();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
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(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
|
||||
|
||||
// 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(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");
|
||||
|
||||
// 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");
|
||||
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)
|
||||
|
||||
// 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;
|
||||
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
if (nDepth < nMinDepth)
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||
CBitcoinAddress address;
|
||||
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
int64 nAmount = 0;
|
||||
int nConf = INT_MAX;
|
||||
if (it != mapTally.end())
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
const string& strAccount = item.second;
|
||||
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
||||
if (it == mapTally.end() && !fIncludeEmpty)
|
||||
continue;
|
||||
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
|
||||
|
||||
// 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)
|
||||
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;
|
||||
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
// 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)));
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
// 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)
|
||||
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)
|
||||
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)
|
||||
"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)
|
||||
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)
|
||||
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)
|
||||
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);
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
||||
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)
|
||||
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,
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
CRITICAL_BLOCK(cs_vMasterKey)
|
||||
{
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
@ -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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
{
|
||||
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:
|
||||
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
24
src/main.cpp
@ -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)
|
||||
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()
|
||||
(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()
|
||||
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)
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Some explaining would be appreciated
|
||||
class COrphan
|
||||
{
|
||||
public:
|
||||
@ -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
14
src/main.h
@ -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;
|
||||
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:
|
||||
bool ProcessAlert();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern std::map<uint256, CTransaction> mapTransactions;
|
||||
|
||||
#endif
|
||||
|
@ -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= \
|
||||
-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
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
128
src/net.cpp
@ -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;
|
||||
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)
|
||||
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)
|
||||
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()
|
||||
|
||||
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)
|
||||
{
|
||||
// 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
405
src/net.h
@ -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;
|
||||
|
||||
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()));
|
||||
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;
|
||||
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
Normal file
312
src/protocol.cpp
Normal file
@ -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
Normal file
150
src/protocol.h
Normal file
@ -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__
|
110
src/script.cpp
110
src/script.cpp
@ -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)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!key.Sign(hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
scriptSigRet << vchSig;
|
||||
}
|
||||
}
|
||||
else if (item.first == OP_PUBKEYHASH)
|
||||
{
|
||||
// Sign and give pubkey
|
||||
CKey key;
|
||||
if (!keystore.GetKey(uint160(item.second), key))
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!key.Sign(hash, vchSig))
|
||||
return false;
|
||||
vchSig.push_back((unsigned char)nHashType);
|
||||
scriptSigRet << vchSig;
|
||||
}
|
||||
}
|
||||
else if (item.first == OP_PUBKEYHASH)
|
||||
{
|
||||
// Sign and give pubkey
|
||||
CKey key;
|
||||
if (!keystore.GetKey(uint160(item.second), key))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -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
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
389
src/ui.cpp
389
src/ui.cpp
@ -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)
|
||||
}
|
||||
|
||||
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)
|
||||
// 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)
|
||||
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)
|
||||
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()
|
||||
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)
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."),
|
||||
_("Passphrase")).ToStdString();
|
||||
|
||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||
bool fWasLocked = pwalletMain->IsLocked();
|
||||
pwalletMain->Lock();
|
||||
|
||||
if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass))
|
||||
{
|
||||
bool fWasLocked = pwalletMain->IsLocked();
|
||||
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 (!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;
|
||||
}
|
||||
string strNewWalletPass;
|
||||
strNewWalletPass.reserve(100);
|
||||
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
|
||||
if (fWasLocked)
|
||||
pwalletMain->Lock();
|
||||
// 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();
|
||||
|
||||
string strNewWalletPass;
|
||||
strNewWalletPass.reserve(100);
|
||||
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
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;
|
||||
}
|
||||
|
||||
// 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."),
|
||||
string strNewWalletPassTest;
|
||||
strNewWalletPassTest.reserve(100);
|
||||
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
|
||||
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||
// be obtained from disk long after bitcoin has run.
|
||||
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
|
||||
_("Passphrase")).ToStdString();
|
||||
|
||||
if (!strNewWalletPass.size())
|
||||
{
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
string strNewWalletPassTest;
|
||||
strNewWalletPassTest.reserve(100);
|
||||
mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
|
||||
// obtain new wallet encrypt/decrypt key, from passphrase
|
||||
// Note that the passphrase is not mlock()d during this entry and could potentially
|
||||
// be obtained from disk long after bitcoin has run.
|
||||
strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."),
|
||||
_("Passphrase")).ToStdString();
|
||||
|
||||
if (strNewWalletPassTest != strNewWalletPass)
|
||||
{
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||
{
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return;
|
||||
}
|
||||
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(_("Wallet Passphrase Changed."), "Bitcoin");
|
||||
wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||
{
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return;
|
||||
}
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity());
|
||||
wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin");
|
||||
}
|
||||
|
||||
void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
|
||||
@ -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)
|
||||
{
|
||||
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
|
||||
#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
|
||||
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)
|
||||
|
||||
if (fBitcoinAddress)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
|
||||
{
|
||||
bool fWasLocked = pwalletMain->IsLocked();
|
||||
if (!GetWalletPassphrase())
|
||||
return;
|
||||
bool fWasLocked = pwalletMain->IsLocked();
|
||||
if (!GetWalletPassphrase())
|
||||
return;
|
||||
|
||||
string strError;
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||
{
|
||||
// Send to bitcoin address
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey.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)
|
||||
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)
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
if (!Status(_("Sending payment...")))
|
||||
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);
|
||||
|
||||
Status(_("Waiting for confirmation..."));
|
||||
MainFrameRepaint();
|
||||
}
|
||||
|
||||
void SendingDialogOnReply3(void* parg, CDataStream& vRecv)
|
||||
@ -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)
|
||||
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)
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
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);
|
||||
|
@ -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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
257
src/wallet.cpp
257
src/wallet.cpp
@ -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
|
||||
|
||||
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)
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||
|
||||
CMasterKey kMasterKey;
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
CRITICAL_BLOCK(cs_wallet)
|
||||
{
|
||||
if (IsCrypted())
|
||||
return false;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||
|
||||
CMasterKey kMasterKey;
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
|
||||
if (fFileBacked)
|
||||
{
|
||||
@ -191,6 +188,7 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase)
|
||||
|
||||
Lock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
{
|
||||
// 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
|
||||
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)
|
||||
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)
|
||||
int ret = 0;
|
||||
|
||||
CBlockIndex* pindex = pindexStart;
|
||||
CRITICAL_BLOCK(cs_mapWallet)
|
||||
CRITICAL_BLOCK(cs_wallet)
|
||||
{
|
||||
while (pindex)
|
||||
{
|
||||
@ -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()
|
||||
// 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()
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
|
||||
// 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,
|
||||
|
||||
|
||||
|
||||
// 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)
|
||||
// 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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
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
17
src/wallet.h
@ -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:
|
||||
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:
|
||||
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:
|
||||
{
|
||||
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:
|
||||
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:
|
||||
|
||||
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…
Reference in New Issue
Block a user