aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro19
-rw-r--r--contrib/gitian-descriptors/deps-win32.yml1
-rw-r--r--contrib/gitian-descriptors/gitian.yml2
-rw-r--r--contrib/homebrew/makefile.osx.patch5
-rw-r--r--contrib/qos/README3
-rw-r--r--contrib/qos/tc.sh41
-rw-r--r--contrib/test-patches/bitcoind-comparison.patch196
-rw-r--r--contrib/test-patches/temp-revert-1.patch21
-rw-r--r--contrib/test-patches/temp-revert-3.patch34
-rw-r--r--contrib/test-patches/temp-revert-4.patch110
-rw-r--r--doc/README.md46
-rw-r--r--doc/assets-attribution.md104
-rw-r--r--doc/build-msw.md25
-rw-r--r--doc/build-osx.md39
-rw-r--r--doc/build-unix.md8
-rw-r--r--doc/files.md23
-rw-r--r--doc/readme-qt.md128
-rw-r--r--doc/readme-qt.rst6
-rw-r--r--doc/release-notes.md77
-rw-r--r--doc/release-process.md10
-rw-r--r--doc/tor.md89
-rw-r--r--share/pixmaps/bitcoin.icobin353118 -> 68756 bytes
-rw-r--r--share/qt/Info.plist2
-rw-r--r--share/setup.nsi2
-rw-r--r--src/alert.cpp7
-rw-r--r--src/allocators.h13
-rw-r--r--src/base58.h127
-rw-r--r--src/bitcoind.cpp141
-rw-r--r--src/bitcoinrpc.cpp54
-rw-r--r--src/bitcoinrpc.h14
-rw-r--r--src/bloom.cpp2
-rw-r--r--src/chainparams.cpp287
-rw-r--r--src/chainparams.h102
-rw-r--r--src/checkpoints.cpp12
-rw-r--r--src/checkpoints.h2
-rw-r--r--src/clientversion.h2
-rw-r--r--src/core.cpp7
-rw-r--r--src/core.h859
-rw-r--r--src/crypter.cpp6
-rw-r--r--src/crypter.h4
-rw-r--r--src/db.cpp16
-rw-r--r--src/db.h6
-rw-r--r--src/hash.h11
-rw-r--r--src/init.cpp357
-rw-r--r--src/key.cpp461
-rw-r--r--src/key.h255
-rw-r--r--src/keystore.cpp86
-rw-r--r--src/keystore.h21
-rwxr-xr-xsrc/leveldb/build_detect_platform6
-rw-r--r--src/main.cpp901
-rw-r--r--src/main.h1214
-rw-r--r--src/makefile.linux-mingw7
-rw-r--r--src/makefile.mingw7
-rw-r--r--src/makefile.osx7
-rw-r--r--src/makefile.unix7
-rw-r--r--src/net.cpp196
-rw-r--r--src/net.h15
-rw-r--r--src/protocol.cpp7
-rw-r--r--src/protocol.h11
-rw-r--r--src/qt/addressbookpage.cpp5
-rw-r--r--src/qt/bitcoin.cpp28
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/bitcoingui.cpp78
-rw-r--r--src/qt/bitcoingui.h6
-rw-r--r--src/qt/bitcoinstrings.cpp2
-rw-r--r--src/qt/clientmodel.cpp3
-rw-r--r--src/qt/forms/overviewpage.ui42
-rw-r--r--src/qt/guiutil.cpp77
-rw-r--r--src/qt/locale/bitcoin_af_ZA.ts2917
-rw-r--r--src/qt/locale/bitcoin_ar.ts2
-rw-r--r--src/qt/locale/bitcoin_de.ts2
-rw-r--r--src/qt/locale/bitcoin_el_GR.ts395
-rw-r--r--src/qt/locale/bitcoin_es.ts24
-rw-r--r--src/qt/locale/bitcoin_ja.ts102
-rw-r--r--src/qt/locale/bitcoin_la.ts24
-rw-r--r--src/qt/locale/bitcoin_nl.ts12
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts8
-rw-r--r--src/qt/locale/bitcoin_pt_PT.ts12
-rw-r--r--src/qt/locale/bitcoin_sk.ts56
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts2
-rw-r--r--src/qt/macdockiconhandler.mm38
-rw-r--r--src/qt/macnotificationhandler.h25
-rw-r--r--src/qt/macnotificationhandler.mm65
-rw-r--r--src/qt/notificator.cpp43
-rw-r--r--src/qt/notificator.h12
-rw-r--r--src/qt/optionsdialog.cpp3
-rw-r--r--src/qt/overviewpage.cpp1
-rw-r--r--src/qt/paymentserver.cpp2
-rw-r--r--src/qt/qrcodedialog.cpp2
-rw-r--r--src/qt/rpcconsole.cpp8
-rw-r--r--src/qt/sendcoinsdialog.cpp4
-rw-r--r--src/qt/signverifymessagedialog.cpp6
-rw-r--r--src/qt/splashscreen.cpp3
-rw-r--r--src/qt/transactiondesc.cpp4
-rw-r--r--src/qt/transactionrecord.cpp4
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp4
-rw-r--r--src/qt/walletframe.h3
-rw-r--r--src/qt/walletstack.h1
-rw-r--r--src/qt/walletview.cpp8
-rw-r--r--src/rpcblockchain.cpp43
-rw-r--r--src/rpcdump.cpp225
-rw-r--r--src/rpcmining.cpp52
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/rpcrawtransaction.cpp8
-rw-r--r--src/rpcwallet.cpp109
-rw-r--r--src/script.cpp92
-rw-r--r--src/script.h13
-rw-r--r--src/test/DoS_tests.cpp3
-rw-r--r--src/test/base58_tests.cpp31
-rw-r--r--src/test/bloom_tests.cpp11
-rw-r--r--src/test/checkblock_tests.cpp4
-rw-r--r--src/test/data/tx_invalid.json9
-rw-r--r--src/test/data/tx_valid.json20
-rw-r--r--src/test/getarg_tests.cpp26
-rw-r--r--src/test/key_tests.cpp96
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/rpc_tests.cpp35
-rw-r--r--src/test/script_P2SH_tests.cpp32
-rw-r--r--src/test/script_tests.cpp8
-rw-r--r--src/test/sigopcount_tests.cpp4
-rw-r--r--src/test/transaction_tests.cpp24
-rw-r--r--src/test/util_tests.cpp24
-rw-r--r--src/txdb.cpp3
-rw-r--r--src/util.cpp27
-rw-r--r--src/util.h30
-rw-r--r--src/wallet.cpp162
-rw-r--r--src/wallet.h24
-rw-r--r--src/walletdb.cpp157
-rw-r--r--src/walletdb.h63
130 files changed, 7744 insertions, 3854 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index a217836df8..1d62941e68 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -3,8 +3,9 @@ TARGET = bitcoin-qt
macx:TARGET = "Bitcoin-Qt"
VERSION = 0.8.2
INCLUDEPATH += src src/json src/qt
-QT += network
-DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
+QT += core gui network
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+DEFINES += BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
CONFIG += no_include_pwd
CONFIG += thread
@@ -146,6 +147,7 @@ HEADERS += src/qt/bitcoingui.h \
src/addrman.h \
src/base58.h \
src/bignum.h \
+ src/chainparams.h \
src/checkpoints.h \
src/compat.h \
src/sync.h \
@@ -153,6 +155,7 @@ HEADERS += src/qt/bitcoingui.h \
src/hash.h \
src/uint256.h \
src/serialize.h \
+ src/core.h \
src/main.h \
src/net.h \
src/key.h \
@@ -225,6 +228,7 @@ SOURCES += src/qt/bitcoin.cpp \
src/qt/editaddressdialog.cpp \
src/qt/bitcoinaddressvalidator.cpp \
src/alert.cpp \
+ src/chainparams.cpp \
src/version.cpp \
src/sync.cpp \
src/util.cpp \
@@ -232,6 +236,7 @@ SOURCES += src/qt/bitcoin.cpp \
src/netbase.cpp \
src/key.cpp \
src/script.cpp \
+ src/core.cpp \
src/main.cpp \
src/init.cpp \
src/net.cpp \
@@ -312,6 +317,7 @@ DEFINES += BITCOIN_QT_TEST
macx: CONFIG -= app_bundle
}
+# Todo: Remove this line when switching to Qt5, as that option was removed
CODECFORTR = UTF-8
# for lrelease/lupdate
@@ -335,7 +341,8 @@ QMAKE_EXTRA_COMPILERS += TSQM
OTHER_FILES += README.md \
doc/*.rst \
doc/*.txt \
- doc/README \
+ doc/*.md \
+ src/bitcoind.cpp \
src/qt/res/bitcoin-qt.rc \
src/test/*.cpp \
src/test/*.h \
@@ -393,9 +400,9 @@ win32:!contains(MINGW_THREAD_BUGFIX, 0) {
DEFINES += _FILE_OFFSET_BITS=64
}
-macx:HEADERS += src/qt/macdockiconhandler.h
-macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
-macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
+macx:HEADERS += src/qt/macdockiconhandler.h src/qt/macnotificationhandler.h
+macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm src/qt/macnotificationhandler.mm
+macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit -framework CoreServices
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
macx:ICON = src/qt/res/icons/bitcoin.icns
macx:QMAKE_CFLAGS_THREAD += -pthread
diff --git a/contrib/gitian-descriptors/deps-win32.yml b/contrib/gitian-descriptors/deps-win32.yml
index 106bd06a9b..90f4c6c4be 100644
--- a/contrib/gitian-descriptors/deps-win32.yml
+++ b/contrib/gitian-descriptors/deps-win32.yml
@@ -10,6 +10,7 @@ packages:
- "zip"
- "faketime"
- "wine"
+- "psmisc"
reference_datetime: "2011-01-30 00:00:00"
remotes: []
files:
diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml
index 8243c5c301..195d0e36ff 100644
--- a/contrib/gitian-descriptors/gitian.yml
+++ b/contrib/gitian-descriptors/gitian.yml
@@ -43,7 +43,7 @@ script: |
cd bitcoin
mkdir -p $OUTDIR/src
git archive HEAD | tar -x -C $OUTDIR/src
- cp $OUTDIR/src/doc/README $OUTDIR
+ cp $OUTDIR/src/doc/README.md $OUTDIR
cp $OUTDIR/src/COPYING $OUTDIR
cd src
make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 DEBUGFLAGS=
diff --git a/contrib/homebrew/makefile.osx.patch b/contrib/homebrew/makefile.osx.patch
index 340de0efdf..287db2fdf2 100644
--- a/contrib/homebrew/makefile.osx.patch
+++ b/contrib/homebrew/makefile.osx.patch
@@ -1,5 +1,5 @@
diff --git a/src/makefile.osx b/src/makefile.osx
-index 8b7c559..8a0560c 100644
+index bef0ef3..07ef8d3 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -7,17 +7,21 @@
@@ -28,7 +28,7 @@ index 8b7c559..8a0560c 100644
USE_UPNP:=1
USE_IPV6:=1
-@@ -31,13 +35,13 @@ ifdef STATIC
+@@ -31,14 +35,14 @@ ifdef STATIC
TESTLIBS += \
$(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
LIBS += \
@@ -38,6 +38,7 @@ index 8b7c559..8a0560c 100644
$(DEPSDIR)/lib/libboost_filesystem-mt.a \
$(DEPSDIR)/lib/libboost_program_options-mt.a \
$(DEPSDIR)/lib/libboost_thread-mt.a \
+ $(DEPSDIR)/lib/libboost_chrono-mt.a \
- $(DEPSDIR)/lib/libssl.a \
- $(DEPSDIR)/lib/libcrypto.a \
+ $(OPENSSLDIR)/lib/libssl.a \
diff --git a/contrib/qos/README b/contrib/qos/README
new file mode 100644
index 0000000000..f419685744
--- /dev/null
+++ b/contrib/qos/README
@@ -0,0 +1,3 @@
+This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. It limits outbound TCP traffic with a source or destination port of 8333, but not if the destination IP is within a LAN (defined as 192.168.x.x).
+
+This means one can have an always-on bitcoind instance running, and another local bitcoind/bitcoin-qt instance which connects to this node and receives blocks from it.
diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh
new file mode 100644
index 0000000000..f620604212
--- /dev/null
+++ b/contrib/qos/tc.sh
@@ -0,0 +1,41 @@
+#network interface on which to limit traffic
+IF="eth0"
+#limit of the network interface in question
+LINKCEIL="1gbit"
+#limit outbound Bitcoin protocol traffic to this rate
+LIMIT="160kbit"
+#defines the address space for which you wish to disable rate limiting
+LOCALNET="192.168.0.0/16"
+
+#delete existing rules
+tc qdisc del dev ${IF} root
+
+#add root class
+tc qdisc add dev ${IF} root handle 1: htb default 10
+
+#add parent class
+tc class add dev ${IF} parent 1: classid 1:1 htb rate ${LINKCEIL} ceil ${LINKCEIL}
+
+#add our two classes. one unlimited, another limited
+tc class add dev ${IF} parent 1:1 classid 1:10 htb rate ${LINKCEIL} ceil ${LINKCEIL} prio 0
+tc class add dev ${IF} parent 1:1 classid 1:11 htb rate ${LIMIT} ceil ${LIMIT} prio 1
+
+#add handles to our classes so packets marked with <x> go into the class with "... handle <x> fw ..."
+tc filter add dev ${IF} parent 1: protocol ip prio 1 handle 1 fw classid 1:10
+tc filter add dev ${IF} parent 1: protocol ip prio 2 handle 2 fw classid 1:11
+
+#delete any existing rules
+#disable for now
+#ret=0
+#while [ $ret -eq 0 ]; do
+# iptables -t mangle -D OUTPUT 1
+# ret=$?
+#done
+
+#limit outgoing traffic to and from port 8333. but not when dealing with a host on the local network
+# (defined by $LOCALNET)
+# --set-mark marks packages matching these criteria with the number "2"
+# these packages are filtered by the tc filter with "handle 2"
+# this filter sends the packages into the 1:11 class, and this class is limited to ${LIMIT}
+iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET} -j MARK --set-mark 0x2
+iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET} -j MARK --set-mark 0x2
diff --git a/contrib/test-patches/bitcoind-comparison.patch b/contrib/test-patches/bitcoind-comparison.patch
deleted file mode 100644
index 7464349b3c..0000000000
--- a/contrib/test-patches/bitcoind-comparison.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-diff --git a/contrib/test-patches/bitcoind-comparison.patch b/contrib/test-patches/bitcoind-comparison.patch
-index 04a8618..519429a 100644
---- a/src/main.cpp
-+++ b/src/main.cpp
-@@ -31,8 +31,8 @@ CTxMemPool mempool;
- unsigned int nTransactionsUpdated = 0;
-
- map<uint256, CBlockIndex*> mapBlockIndex;
--uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
--static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
-+uint256 hashGenesisBlock("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
-+static CBigNum bnProofOfWorkLimit(~uint256(0) >> 1);
- CBlockIndex* pindexGenesisBlock = NULL;
- int nBestHeight = -1;
- uint256 nBestChainWork = 0;
-@@ -1055,7 +1055,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
- int64 nSubsidy = 50 * COIN;
-
- // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
-- nSubsidy >>= (nHeight / 210000);
-+ nSubsidy >>= (nHeight / 150);
-
- return nSubsidy + nFees;
- }
-@@ -2736,9 +2736,9 @@ bool InitBlockIndex() {
- block.hashPrevBlock = 0;
- block.hashMerkleRoot = block.BuildMerkleTree();
- block.nVersion = 1;
-- block.nTime = 1231006505;
-- block.nBits = 0x1d00ffff;
-- block.nNonce = 2083236893;
-+ block.nTime = 1296688602;
-+ block.nBits = 0x207fffff;
-+ block.nNonce = 2;
-
- if (fTestNet)
- {
-@@ -3024,7 +3024,7 @@ bool static AlreadyHave(const CInv& inv)
- // The message start string is designed to be unlikely to occur in normal data.
- // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
- // a large 4-byte int at any alignment.
--unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
-+unsigned char pchMessageStart[4] = { 0xfa, 0xbf, 0xb5, 0xda };
-
-
- void static ProcessGetData(CNode* pfrom)
-diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
-index af28465..ee9a4db 100644
---- a/src/test/miner_tests.cpp
-+++ b/src/test/miner_tests.cpp
-@@ -15,34 +15,117 @@ struct {
- unsigned char extranonce;
- unsigned int nonce;
- } blockinfo[] = {
-- {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
-- {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
-- {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
-- {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
-- {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
-- {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
-- {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
-- {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
-- {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
-- {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
-- {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
-- {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
-- {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
-- {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
-- {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
-- {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
-- {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
-- {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
-- {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
-- {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
-- {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
-- {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
-- {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
-- {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
-- {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
-- {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
-- {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
-- {2, 0xbbbeb305}, {2, 0xfe1c810a},
-+{4, 2762203683},
-+{2, 365113248},
-+{1, 58045772},
-+{1, 1879353512},
-+{2, 3460563607},
-+{2, 1389355416},
-+{1, 2007444690},
-+{2, 3143462790},
-+{2, 2213743660},
-+{1, 1218919771},
-+{1, 4017999107},
-+{2, 1745471173},
-+{2, 142846780},
-+{1, 142326754},
-+{2, 553953301},
-+{2, 3757796778},
-+{1, 4002023946},
-+{2, 3124901826},
-+{1, 2802010589},
-+{1, 877077181},
-+{3, 3593029427},
-+{2, 3969866902},
-+{2, 3392125996},
-+{1, 1805972490},
-+{2, 22889779},
-+{1, 1846647676},
-+{2, 1139340052},
-+{2, 664153912},
-+{2, 3044128027},
-+{2, 3010194979},
-+{2, 3514377385},
-+{2, 1807880922},
-+{1, 1661815113},
-+{2, 2588692156},
-+{2, 1431037239},
-+{1, 3594379210},
-+{2, 2701839377},
-+{1, 1973060452},
-+{2, 4218620174},
-+{1, 3895224884},
-+{1, 3812528857},
-+{3, 1703867851},
-+{2, 3123904294},
-+{5, 36151564},
-+{1, 2846294357},
-+{5, 3499546633},
-+{1, 924279160},
-+{1, 2198572304},
-+{1, 3336802574},
-+{2, 2185182379},
-+{1, 2575632458},
-+{1, 1965161345},
-+{1, 2865408940},
-+{1, 3594887915},
-+{5, 2062161796},
-+{5, 2641251194},
-+{1, 1290342362},
-+{1, 2883355438},
-+{6, 1244984107},
-+{2, 4065479712},
-+{2, 465481866},
-+{1, 2907174016},
-+{1, 2667735788},
-+{1, 363417673},
-+{2, 3519780275},
-+{2, 4165713317},
-+{1, 262548689},
-+{1, 3764359529},
-+{1, 2027001003},
-+{5, 1043862655},
-+{5, 1937481940},
-+{1, 1664585233},
-+{1, 1834979792},
-+{2, 2288070330},
-+{2, 3915617412},
-+{1, 3086662813},
-+{2, 430970259},
-+{1, 1519443249},
-+{2, 1540874280},
-+{2, 2496660261},
-+{1, 2847522842},
-+{1, 977329763},
-+{1, 1458040519},
-+{5, 2241822454},
-+{1, 4253963824},
-+{1, 722247551},
-+{1, 3127905834},
-+{1, 1903207432},
-+{1, 1893631657},
-+{1, 1960201429},
-+{1, 1239890082},
-+{2, 1762702850},
-+{0, 1681675873},
-+{1, 1411795775},
-+{2, 2548720534},
-+{2, 1427588186},
-+{2, 65566621},
-+{1, 2566081936},
-+{1, 3229297415},
-+{1, 3756168812},
-+{1, 826394561},
-+{1, 3015022068},
-+{1, 1935326986},
-+{5, 1648098256},
-+{2, 3545360164},
-+{1, 4106897609},
-+{1, 1528415857},
-+{1, 2707734286},
-+{2, 3149837061},
-+{2, 4263280906},
-+
- };
-
- // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
diff --git a/contrib/test-patches/temp-revert-1.patch b/contrib/test-patches/temp-revert-1.patch
deleted file mode 100644
index a5aec641ce..0000000000
--- a/contrib/test-patches/temp-revert-1.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-commit 4dcc8701ac0eb09d8992d19fb411cee3c9aaf394
-Author: Matt Corallo <git@bluematt.me>
-Date: Sun Mar 24 20:45:44 2013 -0400
-
- Revert "Update unit test to match rule enforcement starts 21 March"
-
- This reverts commit d3e8c6a9d3fad68b0eee4434401ec7b3066399a2.
-
-diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
-index 3cfb6db..e167def 100644
---- a/src/test/checkblock_tests.cpp
-+++ b/src/test/checkblock_tests.cpp
-@@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(May15)
- if (read_block("Mar12Fork.dat", forkingBlock))
- {
- CValidationState state;
-- forkingBlock.nTime = tMay15-1; // Invalidates PoW
-+ BOOST_CHECK(!forkingBlock.CheckBlock(state, true, true));
- BOOST_CHECK(!forkingBlock.CheckBlock(state, false, false));
-
- // After May 15'th, big blocks are OK:
diff --git a/contrib/test-patches/temp-revert-3.patch b/contrib/test-patches/temp-revert-3.patch
deleted file mode 100644
index 5c0775dfa5..0000000000
--- a/contrib/test-patches/temp-revert-3.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-commit ba84709c65b911798ddae1285d807f4cd036990d
-Author: Matt Corallo <git@bluematt.me>
-Date: Sun Mar 24 20:45:56 2013 -0400
-
- Revert "Before 15 May, limit created block size to 500K"
-
- This reverts commit 402f19b64530775a7e4ded025c80d8c16a55e454.
-
-diff --git a/src/main.cpp b/src/main.cpp
-index 22baf0f..51ada0a 100644
---- a/src/main.cpp
-+++ b/src/main.cpp
-@@ -2057,8 +2057,8 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
- return state.DoS(100, error("CheckBlock() : size limits failed"));
-
- // Special short-term limits to avoid 10,000 BDB lock limit:
-- if (GetBlockTime() >= 1363867200 && // start enforcing 21 March 2013, noon GMT
-- GetBlockTime() < 1368576000) // stop enforcing 15 May 2013 00:00:00
-+ if (GetBlockTime() > 1363039171 && // 11 March 2013, timestamp of block before the big fork
-+ GetBlockTime() < 1368576000) // 15 May 2013 00:00:00
- {
- // Rule is: #unique txids referenced <= 4,500
- // ... to prevent 10,000 BDB lock exhaustion on old clients
-@@ -4155,10 +4155,6 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
- // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
- nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
-
-- // Special compatibility rule before 15 May: limit size to 500,000 bytes:
-- if (GetAdjustedTime() < 1368576000)
-- nBlockMaxSize = std::min(nBlockMaxSize, (unsigned int)(MAX_BLOCK_SIZE_GEN));
--
- // How much of the block should be dedicated to high-priority transactions,
- // included regardless of the fees they pay
- unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
diff --git a/contrib/test-patches/temp-revert-4.patch b/contrib/test-patches/temp-revert-4.patch
deleted file mode 100644
index f93d7549c0..0000000000
--- a/contrib/test-patches/temp-revert-4.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-commit ca96b88b61f647d4f56d5d06321dda08a43bf92f
-Author: Matt Corallo <git@bluematt.me>
-Date: Sun Mar 24 20:46:01 2013 -0400
-
- Revert "CheckBlock rule until 15-May for 10,000 BDB lock compatibility"
-
- This reverts commit 8c222dca4f961ad13ec64d690134a40d09b20813.
-
-diff --git a/src/main.cpp b/src/main.cpp
-index 51ada0a..9a06dbf 100644
---- a/src/main.cpp
-+++ b/src/main.cpp
-@@ -2056,25 +2056,6 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
- if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
- return state.DoS(100, error("CheckBlock() : size limits failed"));
-
-- // Special short-term limits to avoid 10,000 BDB lock limit:
-- if (GetBlockTime() > 1363039171 && // 11 March 2013, timestamp of block before the big fork
-- GetBlockTime() < 1368576000) // 15 May 2013 00:00:00
-- {
-- // Rule is: #unique txids referenced <= 4,500
-- // ... to prevent 10,000 BDB lock exhaustion on old clients
-- set<uint256> setTxIn;
-- for (size_t i = 0; i < vtx.size(); i++)
-- {
-- setTxIn.insert(vtx[i].GetHash());
-- if (i == 0) continue; // skip coinbase txin
-- BOOST_FOREACH(const CTxIn& txin, vtx[i].vin)
-- setTxIn.insert(txin.prevout.hash);
-- }
-- size_t nTxids = setTxIn.size();
-- if (nTxids > 4500)
-- return error("CheckBlock() : 15 May maxlocks violation");
-- }
--
- // Check proof of work matches claimed amount
- if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
- return state.DoS(50, error("CheckBlock() : proof of work failed"));
-diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
-deleted file mode 100644
-index e167def..0000000
---- a/src/test/checkblock_tests.cpp
-+++ /dev/null
-@@ -1,66 +0,0 @@
--//
--// Unit tests for block.CheckBlock()
--//
--#include <algorithm>
--
--#include <boost/assign/list_of.hpp> // for 'map_list_of()'
--#include <boost/date_time/posix_time/posix_time_types.hpp>
--#include <boost/test/unit_test.hpp>
--#include <boost/foreach.hpp>
--
--#include "main.h"
--#include "wallet.h"
--#include "net.h"
--#include "util.h"
--
--BOOST_AUTO_TEST_SUITE(CheckBlock_tests)
--
--bool
--read_block(const std::string& filename, CBlock& block)
--{
-- namespace fs = boost::filesystem;
-- fs::path testFile = fs::current_path() / "test" / "data" / filename;
--#ifdef TEST_DATA_DIR
-- if (!fs::exists(testFile))
-- {
-- testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
-- }
--#endif
-- FILE* fp = fopen(testFile.string().c_str(), "rb");
-- if (!fp) return false;
--
-- fseek(fp, 8, SEEK_SET); // skip msgheader/size
--
-- CAutoFile filein = CAutoFile(fp, SER_DISK, CLIENT_VERSION);
-- if (!filein) return false;
--
-- filein >> block;
--
-- return true;
--}
--
--BOOST_AUTO_TEST_CASE(May15)
--{
-- // Putting a 1MB binary file in the git repository is not a great
-- // idea, so this test is only run if you manually download
-- // test/data/Mar12Fork.dat from
-- // http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/Mar12Fork.dat/download
-- unsigned int tMay15 = 1368576000;
-- SetMockTime(tMay15); // Test as if it was right at May 15
--
-- CBlock forkingBlock;
-- if (read_block("Mar12Fork.dat", forkingBlock))
-- {
-- CValidationState state;
-- BOOST_CHECK(!forkingBlock.CheckBlock(state, true, true));
-- BOOST_CHECK(!forkingBlock.CheckBlock(state, false, false));
--
-- // After May 15'th, big blocks are OK:
-- forkingBlock.nTime = tMay15; // Invalidates PoW
-- BOOST_CHECK(forkingBlock.CheckBlock(state, false, false));
-- }
--
-- SetMockTime(0);
--}
--
--BOOST_AUTO_TEST_SUITE_END()
diff --git a/doc/README.md b/doc/README.md
index cdd31057ad..1238033fb7 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,10 +1,9 @@
-Bitcoin 0.8.2 BETA
+Bitcoin 0.8.2 BETA
====================
Copyright (c) 2009-2013 Bitcoin Developers
-Distributed under the MIT/X11 software license, see the accompanying
-file COPYING or http://www.opensource.org/licenses/mit-license.php.
+Distributed under the [MIT/X11 software license](http://www.opensource.org/licenses/mit-license.php).
This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](http://www.openssl.org/). This product includes
cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard.
@@ -19,8 +18,13 @@ with each other, with the help of a P2P network to check for double-spending.
Setup
---------------------
+[Bitcoin-Qt](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions; depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more.
+
+### Unix
+
You need the Qt4 run-time libraries to run Bitcoin-Qt. On Debian or Ubuntu:
- `sudo apt-get install libqtgui4`
+
+ sudo apt-get install libqtgui4
Unpack the files into a directory and run:
@@ -29,18 +33,38 @@ Unpack the files into a directory and run:
- bin/64/bitcoin-qt (GUI, 64-bit)
- bin/64/bitcoind (headless, 64-bit)
-See the documentation at the [Bitcoin Wiki](https://en.bitcoin.it/wiki/Main_Page)
-for help and more information.
-Other Pages
+### Windows
+
+Unpack the files into a directory and run bitcoin-qt.exe.
+
+### Need Help?
+
+* See the documentation at the [Bitcoin Wiki](https://en.bitcoin.it/wiki/Main_Page)
+for help and more information.
+* Ask for help on [#bitcoin](http://webchat.freenode.net?channels=bitcoin) on Freenode. If you don't have an IRC client use [webchat here](http://webchat.freenode.net?channels=bitcoin).
+* Ask for help on the [BitcoinTalk](https://bitcointalk.org/) forums.
+
+Building
---------------------
-- [Unix Build Notes](build-unix.md)
+- [Bitcoin-Qt Readme](readme-qt.md)
- [OSX Build Notes](build-osx.md)
+- [Unix Build Notes](build-unix.md)
- [Windows Build Notes](build-msw.md)
+
+Development
+---------------------
- [Coding Guidelines](coding.md)
-- [Release Process](release-process.md)
-- [Release Notes](release-notes.md)
- [Multiwallet Qt Development](multiwallet-qt.md)
+- [Release Notes](release-notes.md)
+- [Release Process](release-process.md)
+- [Source Code Documentation (External Link)](https://dev.visucore.com/bitcoin/doxygen/)
+- [Translation Process](translation_process.md)
- [Unit Tests](unit-tests.md)
-- [Translation Process](translation_process.md) \ No newline at end of file
+
+Other Pages
+---------------------
+- [Assets Attribution](assets-attribution.md)
+- [Files](files.md)
+- [Tor Support](tor.md) \ No newline at end of file
diff --git a/doc/assets-attribution.md b/doc/assets-attribution.md
new file mode 100644
index 0000000000..e85e74522d
--- /dev/null
+++ b/doc/assets-attribution.md
@@ -0,0 +1,104 @@
+The following is a list of assets used in the bitcoin source and their proper attribution.
+
+[Wladimir van der Laan](https://github.com/laanwj)
+-----------------------
+#### Info
+* License: MIT
+### Assets Used
+
+ src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
+ src/qt/res/src/clock_green.svg, src/qt/res/src/clock1.svg,
+ src/qt/res/src/clock2.svg, src/qt/res/src/clock3.svg,
+ src/qt/res/src/clock4.svg, src/qt/res/src/clock5.svg,
+ src/qt/res/src/inout.svg, src/qt/res/src/questionmark.svg
+
+[David Vignoni](www.icon-king.com)
+-----------------------
+
+### Info
+* Icon Pack: NUVOLA ICON THEME for KDE 3.x
+* Designer: David Vignoni (david@icon-king.com)
+* License: LGPL
+* Site: [http://www.icon-king.com/projects/nuvola/](http://www.icon-king.com/projects/nuvola/)
+
+### Assets Used
+ src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
+ src/qt/res/icons/history.png, src/qt/res/icons/key.png,
+ src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
+ src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
+ src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png
+
+schollidesign
+-----------------------
+
+### Info
+* Icon Pack: Human-O2
+* Designer: schollidesign
+* License: GNU/GPL
+* Site: [http://findicons.com/icon/93743/blocks_gnome_netstatus_0](http://findicons.com/icon/93743/blocks_gnome_netstatus_0)
+
+### Assets Used
+ src/qt/res/icons/connect*.png
+
+md2k7
+-----------------------
+
+### Info
+* Designer: md2k7
+* Site: https://bitcointalk.org/index.php?topic=15276.0
+* License: You are free to do with these icons as you wish, including selling,
+ copying, modifying etc.
+* License: MIT
+
+### Assets Used
+ src/qt/res/icons/transaction*.png
+
+[Everaldo.com](http://www.everaldo.com)
+-----------------------
+
+### Info
+* Designer: [http://www.everaldo.com](http://www.everaldo.com)
+* Icon Pack: Crystal SVG
+* License: LGPL
+
+### Assets Used
+ src/qt/res/icons/configure.png, src/qt/res/icons/quit.png,
+ src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png,
+ src/qt/res/icons/add.png, src/qt/res/icons/edit.png,
+ src/qt/res/icons/remove.png (edited)
+
+Everaldo (Everaldo Coelho)
+-----------------------
+
+### Info
+* Icon Pack: Kids
+* Designer: Everaldo (Everaldo Coelho)
+* License: GNU/GPL
+* Site: [http://findicons.com/icon/17102/reload?id=17102](http://findicons.com/icon/17102/reload?id=17102)
+### Assets Used
+ scripts/img/reload.xcf (modified), src/qt/res/movies/update_spinner.mng
+
+[Vignoni David](http://www.oxygen-icons.org/)
+-----------------------
+
+### Info
+* Designer: Vignoni David
+* Site: http://www.oxygen-icons.org/
+* License: Oxygen icon theme is dual licensed. You may copy it under the Creative Common Attribution-ShareAlike 3.0 License or the GNU Library General Public License.
+
+### Assets Used
+ src/qt/res/icons/debugwindow.png
+
+Jonas Schnelli
+-----------------------
+
+### Info
+* Designer: Jonas Schnelli (based on the original bitcoin logo from Bitboy)
+* License: MIT
+
+### Assets Used
+ src/qt/res/icons/bitcoin.icns, src/qt/res/src/bitcoin.svg,
+ src/qt/res/src/bitcoin.ico, src/qt/res/src/bitcoin.png,
+ src/qt/res/src/bitcoin_testnet.png, docs/bitcoin_logo_doxygen.png,
+ src/qt/res/icons/toolbar.png, src/qt/res/icons/toolbar_testnet.png,
+ src/qt/res/images/splash.png, src/qt/res/images/splash_testnet.png \ No newline at end of file
diff --git a/doc/build-msw.md b/doc/build-msw.md
index b7abe28877..6976c6a560 100644
--- a/doc/build-msw.md
+++ b/doc/build-msw.md
@@ -1,17 +1,9 @@
-Copyright (c) 2009-2013 Bitcoin Developers
-
-Distributed under the MIT/X11 software license, see the accompanying
-file COPYING or http://www.opensource.org/licenses/mit-license.php.
-This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](http://www.openssl.org/). This product includes
-cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard.
-
-
-See readme-qt.rst for instructions on building Bitcoin-Qt, the
-graphical user interface.
-
WINDOWS BUILD NOTES
===================
+See [readme-qt.rst](readme-qt.rst) for instructions on building Bitcoin-Qt, the
+graphical user interface.
+
Compilers Supported
-------------------
TODO: What works?
@@ -22,11 +14,12 @@ Dependencies
------------
Libraries you need to download separately and build:
- default path download
-OpenSSL \openssl-1.0.1c-mgw http://www.openssl.org/source/
-Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html
-Boost \boost-1.50.0-mgw http://www.boost.org/users/download/
-miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/
+ name default path download
+ --------------------------------------------------------------------------------------------------------------------
+ OpenSSL \openssl-1.0.1c-mgw http://www.openssl.org/source/
+ Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html
+ Boost \boost-1.50.0-mgw http://www.boost.org/users/download/
+ miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/
Their licenses:
diff --git a/doc/build-osx.md b/doc/build-osx.md
index d9aa779f87..6f50cf9457 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,38 +1,15 @@
-Mac OS X bitcoind build instructions
+Mac OS X Build Instructions and Notes
====================================
-
-Authors
--------
-
-* Laszlo Hanyecz <solar@heliacal.net>
-* Douglas Huff <dhuff@jrbobdobbs.org>
-* Colin Dean <cad@cad.cx>
-* Gavin Andresen <gavinandresen@gmail.com>
-
-License
--------
-
-Copyright (c) 2009-2012 Bitcoin Developers
-
-Distributed under the MIT/X11 software license, see the accompanying
-file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-This product includes software developed by the OpenSSL Project for use in
-the OpenSSL Toolkit (http://www.openssl.org/).
-
-This product includes cryptographic software written by
-Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.
+This guide will show you how to build bitcoind(headless client) for OSX.
Notes
-----
-See `doc/readme-qt.rst` for instructions on building Bitcoin-Qt, the
+* See [readme-qt.rst](readme-qt.rst) for instructions on building Bitcoin-Qt, the
graphical user interface.
-
-Tested on OS X 10.5 through 10.8 on Intel processors only. PPC is not
+* Tested on OS X 10.5 through 10.8 on Intel processors only. PPC is not
supported because it is big-endian.
-
-All of the commands should be executed in a Terminal application. The
+* All of the commands should be executed in a Terminal application. The
built-in one is located in `/Applications/Utilities`.
Preparation
@@ -47,13 +24,13 @@ be done in `Xcode > Preferences > Downloads > Components` and generally must
be re-done or updated every time Xcode is updated.
There's an assumption that you already have `git` installed, as well. If
-not, it's the path of least resistance to install Github for Mac
+not, it's the path of least resistance to install [Github for Mac](https://mac.github.com/)
(OS X 10.7+) or
[Git for OS X](https://code.google.com/p/git-osx-installer/). It is also
available via Homebrew or MacPorts.
-You will also need to install [Homebrew](http://mxcl.github.com/homebrew/)
-or [MacPorts](http://www.macports.org/) in order to install library
+You will also need to install [Homebrew](http://mxcl.github.io/homebrew/)
+or [MacPorts](https://www.macports.org/) in order to install library
dependencies. It's largely a religious decision which to choose, but, as of
December 2012, MacPorts is a little easier because you can just install the
dependencies immediately - no other work required. If you're unsure, read
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 6181bb255d..b22df91f0b 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -1,12 +1,6 @@
-Copyright (c) 2009-2013 Bitcoin Developers
-
-Distributed under the MIT/X11 software license, see the accompanying
-file COPYING or http://www.opensource.org/licenses/mit-license.php.
-This product includes software developed by the OpenSSL Project for use in the [OpenSSL Toolkit](http://www.openssl.org/). This product includes
-cryptographic software written by Eric Young ([eay@cryptsoft.com](mailto:eay@cryptsoft.com)), and UPnP software written by Thomas Bernard.
-
UNIX BUILD NOTES
====================
+Some notes on how to build Bitcoin in Unix.
To Build
---------------------
diff --git a/doc/files.md b/doc/files.md
new file mode 100644
index 0000000000..80195535bb
--- /dev/null
+++ b/doc/files.md
@@ -0,0 +1,23 @@
+Used in 0.8.0
+---------------------
+* wallet.dat: personal wallet (BDB) with keys and transactions
+* peers.dat: peer IP address database (custom format); since 0.7.0
+* blocks/blk000??.dat: block data (custom, 128 MiB per file); since 0.8.0
+* blocks/rev000??.dat; block undo data (custom); since 0.8.0 (format changed since pre-0.8)
+* blocks/index/*; block index (LevelDB); since 0.8.0
+* chainstate/*; block chain state database (LevelDB); since 0.8.0
+* database/*: BDB database environment; only used for wallet since 0.8.0
+
+Only used in pre-0.8.0
+---------------------
+* blktree/*; block chain index (LevelDB); since pre-0.8, replaced by blocks/index/* in 0.8.0
+* coins/*; unspent transaction output database (LevelDB); since pre-0.8, replaced by chainstate/* in 0.8.0
+
+Only used before 0.8.0
+---------------------
+* blkindex.dat: block chain index database (BDB); replaced by {chainstate/*,blocks/index/*,blocks/rev000??.dat} in 0.8.0
+* blk000?.dat: block data (custom, 2 GiB per file); replaced by blocks/blk000??.dat in 0.8.0
+
+Only used before 0.7.0
+---------------------
+* addr.dat: peer IP address database (BDB); replaced by peers.dat in 0.7.0
diff --git a/doc/readme-qt.md b/doc/readme-qt.md
new file mode 100644
index 0000000000..083db32794
--- /dev/null
+++ b/doc/readme-qt.md
@@ -0,0 +1,128 @@
+Bitcoin-Qt Readme
+===============================
+Contains build and configuration instructions for Bitcoin-Qt (Qt4 GUI for Bitcoin).
+
+Build Instructions
+---------------------
+
+### Debian
+
+
+First, make sure that the required packages for Qt4 development of your
+distribution are installed, these are
+
+
+
+for Debian and Ubuntu <= 11.10 :
+
+
+ apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
+ libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
+ libssl-dev libdb4.8++-dev
+
+for Ubuntu >= 12.04 (please read the 'Berkely DB version warning' below):
+
+ apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
+ libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
+ libssl-dev libdb++-dev libminiupnpc-dev
+
+For Qt 5 you need the following, otherwise you get an error with lrelease when running qmake:
+
+
+ apt-get install qt5-qmake libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev-tools
+
+then execute the following:
+
+ qmake
+ make
+
+Alternatively, install [Qt Creator](http://qt-project.org/downloads/) and open the `bitcoin-qt.pro` file.
+An executable named `bitcoin-qt` will be built.
+
+
+
+### Mac OS X
+
+* Download and install the [Qt Mac OS X SDK](https://qt-project.org/downloads). It is recommended to also install Apple's Xcode with UNIX tools.
+* Download and install either [MacPorts](https://www.macports.org/) or [HomeBrew](http://mxcl.github.io/homebrew/).
+* Execute the following commands in a terminal to get the dependencies using MacPorts
+
+ sudo port selfupdate
+ sudo port install boost db48 miniupnpc
+
+* Execute the following commands in a terminal to get the dependencies using HomeBrew:
+
+ brew update
+ brew install boost miniupnpc openssl berkeley-db4
+
+- If using HomeBrew, edit `bitcoin-qt.pro` to account for library location differences. There's a diff in `contrib/homebrew/bitcoin-qt-pro.patch` that shows what you need to change, or you can just patch by doing
+
+ patch -p1 < contrib/homebrew/bitcoin.qt.pro.patch
+
+- Open the bitcoin-qt.pro file in Qt Creator and build as normal (cmd+B)
+
+
+Build Configuration Options
+---------------------
+
+### UPnP port forwarding
+
+To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable bitcoin experience), pass the following argument to qmake:
+
+
+
+ qmake "USE_UPNP=1"
+
+(in **Qt Creator**, you can find the setting for additional qmake arguments under "Projects" -> "Build Settings" -> "Build Steps", then click "Details" next to **qmake**)
+
+This requires miniupnpc for UPnP port mapping. It can be downloaded from [here](
+http://miniupnp.tuxfamily.org/files/). UPnP support is not compiled in by default.
+
+Set USE_UPNP to a different value to control this:
+
+
+ USE_UPNP=- no UPnP support, miniupnpc not required;
+ USE_UPNP=0 (the default) built with UPnP, support turned off by default at runtime;
+ USE_UPNP=1 build with UPnP support turned on by default at runtime.
+
+### Notification support for recent (k)ubuntu versions
+
+To see desktop notifications on (k)ubuntu versions starting from 10.04, enable usage of the
+FreeDesktop notification interface through DBUS using the following qmake option:
+
+
+
+ qmake "USE_DBUS=1"
+
+### Generation of QR codes
+
+[libqrencode](http://fukuchi.org/works/qrencode/) may be used to generate QRCode images for payment requests. Pass the USE_QRCODE flag to qmake to control this:
+
+
+ USE_QRCODE=0 (the default) No QRCode support - libarcode not required
+ USE_QRCODE=1 QRCode support enabled
+
+Warnings
+---------------------
+
+### Berkely DB Version Warning
+
+
+A warning for people using the *static binary* version of Bitcoin on a Linux/UNIX-ish system (tl;dr: **Berkely DB databases are not forward compatible**).
+
+The static binary version of Bitcoin is linked against libdb4.8 (see also [this Debian issue](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621425)).
+
+Now the nasty thing is that databases from 5.X are not compatible with 4.X.
+
+If the globally installed development package of Berkely DB installed on your system is 5.X, any source you build yourself will be linked against that. The first time you run with a 5.X version the database will be upgraded, and 4.X cannot open the new format. This means that you cannot go back to the old statically linked version without significant hassle!
+
+### Ubuntu 11.10 Warning
+
+
+Ubuntu 11.10 has a package called 'qt-at-spi' installed by default. At the time of writing, having that package installed causes bitcoin-qt to crash intermittently. The issue has been reported as [launchpad bug 857790](https://bugs.launchpad.net/ubuntu/+source/qt-at-spi/+bug/857790), but
+isn't yet fixed.
+
+Until the bug is fixed, you can remove the qt-at-spi package to work around the problem, though this will presumably disable screen reader functionality for Qt apps:
+
+ sudo apt-get remove qt-at-spi
+
diff --git a/doc/readme-qt.rst b/doc/readme-qt.rst
index 1bc3d701ae..95cb33650f 100644
--- a/doc/readme-qt.rst
+++ b/doc/readme-qt.rst
@@ -28,6 +28,12 @@ for Ubuntu >= 12.04 (please read the 'Berkely DB version warning' below):
libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
libssl-dev libdb++-dev libminiupnpc-dev
+For Qt 5 you need the following, otherwise you get an error with lrelease when running qmake:
+
+::
+
+ apt-get install qt5-qmake libqt5gui5 libqt5core5 libqt5dbus5 qttools5-dev-tools
+
then execute the following:
::
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 0e0b04bcaa..acaeef1d60 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,80 +1,3 @@
(note: this is a temporary file, to be added-to by anybody, and deleted at
release time)
-Fee Policy changes
-------------------
-
-The default fee for low-priority transactions is lowered from 0.0005 BTC
-(for each 1,000 bytes in the transaction; an average transaction is
-about 500 bytes) to 0.0001 BTC.
-
-Payments (transaction outputs) of 0.543 times the minimum relay fee
-(0.00005430 BTC) are now considered 'non-standard', because storing them
-costs the network more than they are worth and spending them will usually
-cost their owner more in transaction fees than they are worth.
-
-Non-standard transactions are not relayed across the network, are not included
-in blocks by most miners, and will not show up in your wallet until they are
-included in a block.
-
-The default fee policy can be overridden using the -mintxfee and -minrelaytxfee
-command-line options, but note that we intend to replace the hard-coded fees
-with code that automatically calculates and suggests appropriate fees in the
-0.9 release and note that if you set a fee policy significantly different from
-the rest of the network your transactions may never confirm.
-
-Bitcoin-Qt changes
-------------------
-
-- New icon and splash screen
-- Improve reporting of synchronization process
-- Remove hardcoded fee recommendations
-- Improve metadata of executable on MacOSX and Windows
-- Move export button to individual tabs instead of toolbar
-- Add "send coins" command to context menu in address book
-- Add "copy txid" command to copy transaction IDs from transaction overview
-- Save & restore window size and position when showing & hiding window
-- New translations: Arabic (ar), Bosnian (bs), Catalan (ca), Welsh (cy), Esperanto (eo), Interlingua (la), Latvian (lv) and many improvements to current translations
-
-MacOSX:
-
-- OSX support for click-to-pay (bitcoin:) links
-- Fix GUI disappearing problem on MacOSX (issue #1522)
-
-Linux/Unix:
-
-- Copy addresses to middle-mouse-button clipboard
-
-
-Command-line options
---------------------
-
-* `-walletnotify` will call a command on receiving transactions that affect the wallet.
-* `-alertnotify` will call a command on receiving an alert from the network.
-* `-par` now takes a negative number, to leave a certain amount of cores free.
-
-JSON-RPC API changes
---------------------
-
-* `listunspent` now lists account and address infromation.
-* `getinfo` now also returns the time adjustment estimated from your peers.
-* `getpeerinfo` now returns bytessent, bytesrecv and syncnode.
-* `gettxoutsetinfo` returns statistics about the unspent transaction output database.
-* `gettxout` returns information about a specific unspent transaction output.
-
-
-Networking changes
-------------------
-
-* Significant changes to the networking code, reducing latency and memory consumption.
-* Avoid initial block download stalling.
-* Remove IRC seeding support.
-* Performance tweaks.
-* Added testnet DNS seeds.
-
-Wallet compatibility/rescuing
------------------------------
-
-* Cases where wallets cannot be opened in another version/installation should be reduced.
-* `-salvagewallet` now works for encrypted wallets.
-
diff --git a/doc/release-process.md b/doc/release-process.md
index 17d6a089c9..dc2101e1c1 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -17,11 +17,11 @@ Release Process
###tag version in git
- git tag -a v0.8.0
+ git tag -a v(new version, e.g. 0.8.0)
###write release notes. git shortlog helps a lot, for example:
- git shortlog --no-merges v0.7.2..v0.8.0
+ git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0)
* * *
@@ -30,7 +30,7 @@ Release Process
From a directory containing the bitcoin source, gitian-builder and gitian.sigs
export SIGNER=(your gitian key, ie bluematt, sipa, etc)
- export VERSION=0.8.0
+ export VERSION=(new version, e.g. 0.8.0)
cd ./gitian-builder
Fetch and build inputs: (first time, or when dependency versions change)
@@ -134,7 +134,7 @@ Commit your signature to gitian.sigs:
From a directory containing bitcoin source, gitian.sigs and gitian zips
- export VERSION=0.5.1
+ export VERSION=(new version, e.g. 0.8.0)
mkdir bitcoin-${VERSION}-linux-gitian
pushd bitcoin-${VERSION}-linux-gitian
unzip ../bitcoin-${VERSION}-linux-gitian.zip
@@ -161,4 +161,4 @@ From a directory containing bitcoin source, gitian.sigs and gitian zips
popd
- Upload gitian zips to SourceForge
-- Celebrate \ No newline at end of file
+- Celebrate
diff --git a/doc/tor.md b/doc/tor.md
new file mode 100644
index 0000000000..86d56cffd5
--- /dev/null
+++ b/doc/tor.md
@@ -0,0 +1,89 @@
+TOR SUPPORT IN BITCOIN
+======================
+
+It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
+
+The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on a random port. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
+configure Tor.
+
+
+1. Run bitcoin behind a Tor proxy
+---------------------------------
+
+The first step is running Bitcoin behind a Tor proxy. This will already make all
+outgoing connections be anonimized, but more is possible.
+
+ -socks=5 SOCKS5 supports connecting-to-hostname, which can be used instead
+ of doing a (leaking) local DNS lookup. SOCKS5 is the default,
+ but SOCKS4 does not support this. (SOCKS4a does, but isn't
+ implemented).
+
+ -proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
+ server will be used to try to reach .onion addresses as well.
+
+ -tor=ip:port Set the proxy server to use for tor hidden services. You do not
+ need to set this if it's the same as -proxy. You can use -notor
+ to explicitly disable access to hidden service.
+
+ -listen When using -proxy, listening is disabled by default. If you want
+ to run a hidden service (see next section), you'll need to enable
+ it explicitly.
+
+ -connect=X When behind a Tor proxy, you can specify .onion addresses instead
+ -addnode=X of IP addresses or hostnames in these parameters. It requires
+ -seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
+ other P2P nodes.
+
+In a typical situation, this suffices to run behind a Tor proxy:
+
+ ./bitcoin -proxy=127.0.0.1:9050
+
+
+2. Run a bitcoin hidden server
+------------------------------
+
+If you configure your Tor system accordingly, it is possible to make your node also
+reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
+config file):
+
+ HiddenServiceDir /var/lib/tor/bitcoin-service/
+ HiddenServicePort 8333 127.0.0.1:8333
+
+The directory can be different of course, but (both) port numbers should be equal to
+your bitcoind's P2P listen port (8333 by default).
+
+ -externalip=X You can tell bitcoin about its publicly reachable address using
+ this option, and this can be a .onion address. Given the above
+ configuration, you can find your onion address in
+ /var/lib/tor/bitcoin-service/hostname. Onion addresses are given
+ preference for your node to advertize itself with, for connections
+ coming from unroutable addresses (such as 127.0.0.1, where the
+ Tor proxy typically runs).
+
+ -listen You'll need to enable listening for incoming connections, as this
+ is off by default behind a proxy.
+
+ -discover When -externalip is specified, no attempt is made to discover local
+ IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
+ from both Tor and IPv4 (or IPv6), you'll need to either pass your
+ other addresses using -externalip, or explicitly enable -discover.
+ Note that both addresses of a dual-stack system may be easily
+ linkable using traffic analysis.
+
+In a typical situation, where you're only reachable via Tor, this should suffice:
+
+ ./bitcoind -proxy=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -listen
+
+(obviously, replace the Onion address with your own). If you don't care too much
+about hiding your node, and want to be reachable on IPv4 as well, additionally
+specify:
+
+ ./bitcoind ... -discover
+
+and open port 8333 on your firewall (or use -upnp).
+
+If you only want to use Tor to reach onion addresses, but not use it as a proxy
+for normal IPv4/IPv6 communication, use:
+
+ ./bitcoin -tor=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover
+
diff --git a/share/pixmaps/bitcoin.ico b/share/pixmaps/bitcoin.ico
index 48a9822a46..f5480f4161 100644
--- a/share/pixmaps/bitcoin.ico
+++ b/share/pixmaps/bitcoin.ico
Binary files differ
diff --git a/share/qt/Info.plist b/share/qt/Info.plist
index 2312094c4f..6f64c3164b 100644
--- a/share/qt/Info.plist
+++ b/share/qt/Info.plist
@@ -31,5 +31,7 @@
</array>
</dict>
</array>
+ <key>NSHighResolutionCapable</key>
+ <true/>
</dict>
</plist>
diff --git a/share/setup.nsi b/share/setup.nsi
index 4a7b0b1da7..d5f2ffc3f8 100644
--- a/share/setup.nsi
+++ b/share/setup.nsi
@@ -51,7 +51,7 @@ CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
-VIProductVersion 0.8.2.0
+VIProductVersion 0.8.2.2
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
diff --git a/src/alert.cpp b/src/alert.cpp
index 4b029840dd..e00847aadb 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -19,9 +19,6 @@ using namespace std;
map<uint256, CAlert> mapAlerts;
CCriticalSection cs_mapAlerts;
-static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284";
-static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a";
-
void CUnsignedAlert::SetNull()
{
nVersion = 1;
@@ -144,9 +141,7 @@ bool CAlert::RelayTo(CNode* pnode) const
bool CAlert::CheckSignature() const
{
- CKey key;
- if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
- return error("CAlert::CheckSignature() : SetPubKey failed");
+ CPubKey key(Params().AlertKey());
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
return error("CAlert::CheckSignature() : verify signature failed");
diff --git a/src/allocators.h b/src/allocators.h
index eb2aed6721..85af8fe376 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -177,6 +177,19 @@ private:
};
//
+// Functions for directly locking/unlocking memory objects.
+// Intended for non-dynamically allocated structures.
+//
+template<typename T> void LockObject(const T &t) {
+ LockedPageManager::instance.LockRange((void*)(&t), sizeof(T));
+}
+
+template<typename T> void UnlockObject(const T &t) {
+ OPENSSL_cleanse((void*)(&t), sizeof(T));
+ LockedPageManager::instance.UnlockRange((void*)(&t), sizeof(T));
+}
+
+//
// Allocator that locks its contents from being paged
// out of memory and clears its contents before deletion.
//
diff --git a/src/base58.h b/src/base58.h
index be8a541f67..630d6fe9aa 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
+#include "chainparams.h"
#include "bignum.h"
#include "key.h"
#include "script.h"
@@ -270,21 +271,13 @@ public:
class CBitcoinAddress : public CBase58Data
{
public:
- enum
- {
- PUBKEY_ADDRESS = 0,
- SCRIPT_ADDRESS = 5,
- PUBKEY_ADDRESS_TEST = 111,
- SCRIPT_ADDRESS_TEST = 196,
- };
-
bool Set(const CKeyID &id) {
- SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
+ SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
return true;
}
bool Set(const CScriptID &id) {
- SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
+ SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
return true;
}
@@ -295,32 +288,10 @@ public:
bool IsValid() const
{
- unsigned int nExpectedSize = 20;
- bool fExpectTestNet = false;
- switch(nVersion)
- {
- case PUBKEY_ADDRESS:
- nExpectedSize = 20; // Hash of public key
- fExpectTestNet = false;
- break;
- case SCRIPT_ADDRESS:
- nExpectedSize = 20; // Hash of CScript
- fExpectTestNet = false;
- break;
-
- case PUBKEY_ADDRESS_TEST:
- nExpectedSize = 20;
- fExpectTestNet = true;
- break;
- case SCRIPT_ADDRESS_TEST:
- nExpectedSize = 20;
- fExpectTestNet = true;
- break;
-
- default:
- return false;
- }
- return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
+ bool fCorrectSize = vchData.size() == 20;
+ bool fKnownVersion = nVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
+ nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
+ return fCorrectSize && fKnownVersion;
}
CBitcoinAddress()
@@ -345,48 +316,27 @@ public:
CTxDestination Get() const {
if (!IsValid())
return CNoDestination();
- switch (nVersion) {
- case PUBKEY_ADDRESS:
- case PUBKEY_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
+ uint160 id;
+ memcpy(&id, &vchData[0], 20);
+ if (nVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
return CKeyID(id);
- }
- case SCRIPT_ADDRESS:
- case SCRIPT_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
+ else if (nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
return CScriptID(id);
- }
- }
- return CNoDestination();
+ else
+ return CNoDestination();
}
bool GetKeyID(CKeyID &keyID) const {
- if (!IsValid())
+ if (!IsValid() || nVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
return false;
- switch (nVersion) {
- case PUBKEY_ADDRESS:
- case PUBKEY_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
- keyID = CKeyID(id);
- return true;
- }
- default: return false;
- }
+ uint160 id;
+ memcpy(&id, &vchData[0], 20);
+ keyID = CKeyID(id);
+ return true;
}
bool IsScript() const {
- if (!IsValid())
- return false;
- switch (nVersion) {
- case SCRIPT_ADDRESS:
- case SCRIPT_ADDRESS_TEST: {
- return true;
- }
- default: return false;
- }
+ return IsValid() && nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
}
};
@@ -398,39 +348,26 @@ bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const {
class CBitcoinSecret : public CBase58Data
{
public:
- void SetSecret(const CSecret& vchSecret, bool fCompressed)
+ void SetKey(const CKey& vchSecret)
{
- assert(vchSecret.size() == 32);
- SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size());
- if (fCompressed)
+ assert(vchSecret.IsValid());
+ SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
+ if (vchSecret.IsCompressed())
vchData.push_back(1);
}
- CSecret GetSecret(bool &fCompressedOut)
+ CKey GetKey()
{
- CSecret vchSecret;
- vchSecret.resize(32);
- memcpy(&vchSecret[0], &vchData[0], 32);
- fCompressedOut = vchData.size() == 33;
- return vchSecret;
+ CKey ret;
+ ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1);
+ return ret;
}
bool IsValid() const
{
- bool fExpectTestNet = false;
- switch(nVersion)
- {
- case 128:
- break;
-
- case 239:
- fExpectTestNet = true;
- break;
-
- default:
- return false;
- }
- return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
+ bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
+ bool fCorrectVersion = nVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
+ return fExpectedFormat && fCorrectVersion;
}
bool SetString(const char* pszSecret)
@@ -443,9 +380,9 @@ public:
return SetString(strSecret.c_str());
}
- CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
+ CBitcoinSecret(const CKey& vchSecret)
{
- SetSecret(vchSecret, fCompressed);
+ SetKey(vchSecret);
}
CBitcoinSecret()
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
new file mode 100644
index 0000000000..bc23cf5507
--- /dev/null
+++ b/src/bitcoind.cpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "init.h"
+#include "bitcoinrpc.h"
+#include <boost/algorithm/string/predicate.hpp>
+
+void DetectShutdownThread(boost::thread_group* threadGroup)
+{
+ bool shutdown = ShutdownRequested();
+ // Tell the main threads to shutdown.
+ while (!shutdown)
+ {
+ MilliSleep(200);
+ shutdown = ShutdownRequested();
+ }
+ if (threadGroup)
+ threadGroup->interrupt_all();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Start
+//
+bool AppInit(int argc, char* argv[])
+{
+ boost::thread_group threadGroup;
+ boost::thread* detectShutdownThread = NULL;
+
+ bool fRet = false;
+ try
+ {
+ //
+ // Parameters
+ //
+ // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
+ ParseParameters(argc, argv);
+ if (!boost::filesystem::is_directory(GetDataDir(false)))
+ {
+ fprintf(stderr, "Error: Specified directory does not exist\n");
+ Shutdown();
+ }
+ ReadConfigFile(mapArgs, mapMultiArgs);
+
+ if (mapArgs.count("-?") || mapArgs.count("--help"))
+ {
+ // First part of help message is specific to bitcoind / RPC client
+ std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
+ _("Usage:") + "\n" +
+ " bitcoind [options] " + "\n" +
+ " bitcoind [options] <command> [params] " + _("Send command to -server or bitcoind") + "\n" +
+ " bitcoind [options] help " + _("List commands") + "\n" +
+ " bitcoind [options] help <command> " + _("Get help for a command") + "\n";
+
+ strUsage += "\n" + HelpMessage();
+
+ fprintf(stdout, "%s", strUsage.c_str());
+ return false;
+ }
+
+ // Command-line RPC
+ for (int i = 1; i < argc; i++)
+ if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
+ fCommandLine = true;
+
+ if (fCommandLine)
+ {
+ if (!SelectParamsFromCommandLine()) {
+ fprintf(stderr, "Error: invalid combination of -regtest and -testnet.\n");
+ return false;
+ }
+ int ret = CommandLineRPC(argc, argv);
+ exit(ret);
+ }
+#if !defined(WIN32)
+ fDaemon = GetBoolArg("-daemon", false);
+ if (fDaemon)
+ {
+ // Daemonize
+ pid_t pid = fork();
+ if (pid < 0)
+ {
+ fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
+ return false;
+ }
+ if (pid > 0) // Parent process, pid is child process id
+ {
+ CreatePidFile(GetPidFile(), pid);
+ return true;
+ }
+ // Child process falls through to rest of initialization
+
+ pid_t sid = setsid();
+ if (sid < 0)
+ fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
+ }
+#endif
+
+ detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
+ fRet = AppInit2(threadGroup);
+ }
+ catch (std::exception& e) {
+ PrintExceptionContinue(&e, "AppInit()");
+ } catch (...) {
+ PrintExceptionContinue(NULL, "AppInit()");
+ }
+ if (!fRet) {
+ if (detectShutdownThread)
+ detectShutdownThread->interrupt();
+ threadGroup.interrupt_all();
+ }
+
+ if (detectShutdownThread)
+ {
+ detectShutdownThread->join();
+ delete detectShutdownThread;
+ detectShutdownThread = NULL;
+ }
+ Shutdown();
+
+ return fRet;
+}
+
+extern void noui_connect();
+int main(int argc, char* argv[])
+{
+ bool fRet = false;
+ fHaveGUI = false;
+
+ // Connect bitcoind signal handlers
+ noui_connect();
+
+ fRet = AppInit(argc, argv);
+
+ if (fRet && fDaemon)
+ return 0;
+
+ return (fRet ? 0 : 1);
+}
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index a9b73fd5a6..5908126200 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "init.h"
#include "util.h"
#include "sync.h"
@@ -11,17 +12,17 @@
#include "bitcoinrpc.h"
#include "db.h"
+#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ip/v6_only.hpp>
+#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/asio/ssl.hpp>
-#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
@@ -34,14 +35,10 @@ static std::string strRPCUserColonPass;
// These are created by StartRPCThreads, destroyed in StopRPCThreads
static asio::io_service* rpc_io_service = NULL;
+static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
static ssl::context* rpc_ssl_context = NULL;
static boost::thread_group* rpc_worker_group = NULL;
-static inline unsigned short GetDefaultRPCPort()
-{
- return GetBoolArg("-testnet", false) ? 18332 : 8332;
-}
-
Object JSONRPCError(int code, const string& message)
{
Object error;
@@ -246,7 +243,9 @@ static const CRPCCommand vRPCCommands[] =
{ "submitblock", &submitblock, false, false },
{ "listsinceblock", &listsinceblock, false, false },
{ "dumpprivkey", &dumpprivkey, true, false },
+ { "dumpwallet", &dumpwallet, true, false },
{ "importprivkey", &importprivkey, false, false },
+ { "importwallet", &importwallet, false, false },
{ "listunspent", &listunspent, false, false },
{ "getrawtransaction", &getrawtransaction, false, false },
{ "createrawtransaction", &createrawtransaction, false, false },
@@ -257,6 +256,7 @@ static const CRPCCommand vRPCCommands[] =
{ "gettxout", &gettxout, true, false },
{ "lockunspent", &lockunspent, false, false },
{ "listlockunspent", &listlockunspent, false, false },
+ { "verifychain", &verifychain, true, false },
};
CRPCTable::CRPCTable()
@@ -723,8 +723,8 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
void StartRPCThreads()
{
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
- if ((mapArgs["-rpcpassword"] == "") ||
- (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"]))
+ if (((mapArgs["-rpcpassword"] == "") ||
+ (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
{
unsigned char rand_pwd[32];
RAND_bytes(rand_pwd, 32);
@@ -756,7 +756,7 @@ void StartRPCThreads()
rpc_io_service = new asio::io_service();
rpc_ssl_context = new ssl::context(*rpc_io_service, ssl::context::sslv23);
- const bool fUseSSL = GetBoolArg("-rpcssl");
+ const bool fUseSSL = GetBoolArg("-rpcssl", false);
if (fUseSSL)
{
@@ -779,7 +779,7 @@ void StartRPCThreads()
// Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets
const bool loopback = !mapArgs.count("-rpcallowip");
asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
- ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", GetDefaultRPCPort()));
+ ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort()));
boost::system::error_code v6_only_error;
boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
@@ -843,6 +843,7 @@ void StopRPCThreads()
{
if (rpc_io_service == NULL) return;
+ deadlineTimers.clear();
rpc_io_service->stop();
rpc_worker_group->join_all();
delete rpc_worker_group; rpc_worker_group = NULL;
@@ -850,6 +851,26 @@ void StopRPCThreads()
delete rpc_io_service; rpc_io_service = NULL;
}
+void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
+{
+ if (!err)
+ func();
+}
+
+void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64 nSeconds)
+{
+ assert(rpc_io_service != NULL);
+
+ if (deadlineTimers.count(name) == 0)
+ {
+ deadlineTimers.insert(make_pair(name,
+ boost::shared_ptr<deadline_timer>(new deadline_timer(*rpc_io_service))));
+ }
+ deadlineTimers[name]->expires_from_now(posix_time::seconds(nSeconds));
+ deadlineTimers[name]->async_wait(boost::bind(RPCRunHandler, _1, func));
+}
+
+
class JSONRequest
{
public:
@@ -1015,7 +1036,7 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
// Observe safe mode
string strWarning = GetWarnings("rpc");
- if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
+ if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
!pcmd->okSafeMode)
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
@@ -1049,14 +1070,14 @@ Object CallRPC(const string& strMethod, const Array& params)
GetConfigFile().string().c_str()));
// Connect to localhost
- bool fUseSSL = GetBoolArg("-rpcssl");
+ bool fUseSSL = GetBoolArg("-rpcssl", false);
asio::io_service io_service;
ssl::context context(io_service, ssl::context::sslv23);
context.set_options(ssl::context::no_sslv2);
asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
- if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(GetDefaultRPCPort()))))
+ if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))))
throw runtime_error("couldn't connect to server");
// HTTP basic authentication
@@ -1165,6 +1186,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "listunspent" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listunspent" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "listunspent" && n > 2) ConvertTo<Array>(params[2]);
+ if (strMethod == "getblock" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "getrawtransaction" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "createrawtransaction" && n > 0) ConvertTo<Array>(params[0]);
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
@@ -1175,6 +1197,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
+ if (strMethod == "verifychain" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "verifychain" && n > 1) ConvertTo<boost::int64_t>(params[1]);
return params;
}
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 315fd92383..247c47adf9 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -11,6 +11,7 @@
#include <map>
class CBlockIndex;
+class CReserveKey;
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
@@ -88,6 +89,12 @@ void RPCTypeCheck(const json_spirit::Array& params,
void RPCTypeCheck(const json_spirit::Object& o,
const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
+/*
+ Run func nSeconds from now. Uses boost deadline timers.
+ Overrides previous timer <name> (if any).
+ */
+void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64 nSeconds);
+
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
class CRPCCommand
@@ -123,6 +130,9 @@ public:
extern const CRPCTable tableRPC;
+extern void InitRPCMining();
+extern void ShutdownRPCMining();
+
extern int64 nWalletUnlockTime;
extern int64 AmountFromValue(const json_spirit::Value& value);
extern json_spirit::Value ValueFromAmount(int64 amount);
@@ -135,8 +145,11 @@ extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, b
extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp);
+
extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
@@ -195,5 +208,6 @@ extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fH
extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
#endif
diff --git a/src/bloom.cpp b/src/bloom.cpp
index d9ec2efa81..b6799e143d 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -5,7 +5,7 @@
#include <stdlib.h>
#include "bloom.h"
-#include "main.h"
+#include "core.h"
#include "script.h"
#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
new file mode 100644
index 0000000000..3bb62fb793
--- /dev/null
+++ b/src/chainparams.cpp
@@ -0,0 +1,287 @@
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "assert.h"
+
+#include "chainparams.h"
+#include "core.h"
+#include "protocol.h"
+#include "util.h"
+
+//
+// Main network
+//
+
+unsigned int pnSeed[] =
+{
+ 0xe473042e, 0xb177f2ad, 0xd63f3fb2, 0xf864f736, 0x44a23ac7, 0xcf6d9650, 0xd648042e, 0x0536f447,
+ 0x3c654ed0, 0x3e16a5bc, 0xa38e09b0, 0xdfae795b, 0xabfeca5b, 0x94ad7840, 0xf3b9f1c7, 0xbe70e0ad,
+ 0x3bbd09b0, 0x8d0c7dd5, 0x3b2a7332, 0x1a06175e, 0x581f175e, 0xca0d2dcc, 0x0fdbc658, 0xcf591ec7,
+ 0x295a12b2, 0xb4707bce, 0x68bb09b0, 0x4e735747, 0x89709553, 0x05a7814e, 0x5b8ec658, 0x402c5512,
+ 0xe80d0905, 0x17681a5e, 0xc02aa748, 0x9f811741, 0x5f321cb0, 0x23e1ee47, 0xaf7f170c, 0xaa240ab0,
+ 0xedea6257, 0x76106bc1, 0x2cf310cc, 0x08612acb, 0x9c682e4e, 0x8e963c6c, 0x443c795b, 0x22e246b8,
+ 0xfa1f2dcc, 0x90118140, 0x3821042e, 0x33c3fd2e, 0x10046d5b, 0x40d14b3e, 0x7fb8f8ce, 0x67696550,
+ 0xeeecbe58, 0x4f341745, 0x46b8fbd5, 0xc8463932, 0x6b73e862, 0x4c715932, 0x4a6785d5, 0xce3a64c2,
+ 0xde9604c7, 0x9b06884f, 0x18002a45, 0xea9bc345, 0xc4f1c658, 0xe475c1c7, 0xdd3e795b, 0x9722175e,
+ 0x34562f4e, 0x66c46e4e, 0x40bb1243, 0x7d9171d0, 0x17b8dbd5, 0x63cbfd2e, 0x1a08b8d8, 0x6175a73b,
+ 0x228d2660, 0x8627c658, 0x9c566644, 0x38cca5bc, 0x3089de5b, 0x92e25f5d, 0xa393f73f, 0xcc92dc3e,
+ 0x27487446, 0x62cbfd2e, 0x9d983b45, 0xf72a09b0, 0xf75f042e, 0x6434bb6a, 0xb29e77d8, 0x19be4fd9,
+ 0x76443243, 0x9dd72645, 0x694cef43, 0x89c2efd5, 0x5f1c5058, 0x46c6e45b, 0xe1391b40, 0x77ccefd5,
+ 0x472e5a6d, 0x85709553, 0xdd4f5d4c, 0x64ef5a46, 0x7f0ae502, 0xcf08d850, 0x3460042e, 0xeafa2d42,
+ 0x793c9044, 0x9d094746, 0x1ab9b153, 0xbfe9a5bc, 0x34771fb0, 0xb7722e32, 0x1168964b, 0x19b06ab8,
+ 0x19243b25, 0x13188045, 0xb4070905, 0x728ebb5d, 0x44f24ac8, 0xa317fead, 0x642f6a57, 0x3d951f32,
+ 0x3d312e4e, 0xfac4d048, 0xefc4dd50, 0x52b9f1c7, 0xc14d3cc3, 0x0219ea44, 0x3b79d058, 0xfa217242,
+ 0x39c80647, 0xfb697252, 0x1d495a42, 0x0aa81f4e, 0x58249ab8, 0xe6a8e6c3, 0x2bc4dad8, 0x85963c6c,
+ 0xa4ce09b0, 0x2005f536, 0x5cc2703e, 0x1992de43, 0x74e86b4c, 0xe7085653, 0xf5e15a51, 0xb4872b60,
+ 0x29e2b162, 0xa07ea053, 0x8229fd18, 0x4562ec4d, 0x8dec814e, 0x36cfa4cf, 0x96461032, 0x3c8770de,
+ 0xd10a1f5f, 0x95934641, 0x97cd65d0, 0x2e35324a, 0x2566ba1f, 0x1ca1a9d1, 0xb808b8d5, 0xf9a24a5d,
+ 0xafc8d431, 0xe4b8d9b2, 0x0f5321b2, 0x330bc658, 0x74b347ce, 0x972babd5, 0x044f7d4f, 0x06562f4e,
+ 0x8b8d3c6c, 0x3507c658, 0xe4174e4d, 0xf1c009b0, 0x52249ab8, 0x27211772, 0xf6a9ba59, 0x7a391b40,
+ 0x855dc6c0, 0x291f20b2, 0xe29bc345, 0x90963c6c, 0x0af70732, 0x4242a91f, 0x4c531d48, 0xa32df948,
+ 0x627e3044, 0x65be1f54, 0x1a0cbf83, 0x6a443532, 0x8d5f1955, 0xbafa8132, 0x3534bdd5, 0xca019dd9,
+ 0x8a0d9332, 0x5584e7d8, 0x7cd1f25e, 0xeabe3fb2, 0x2945d0d1, 0x46415718, 0x70d6042e, 0x99eb76d0,
+ 0x9ece09b0, 0xb3777418, 0x5e5e91d9, 0x237a3ab0, 0xf512b62e, 0x45dec347, 0x59b7f862, 0x4c443b25,
+ 0x3cc6484b, 0x9a8ec6d1, 0x021eea44, 0xc9483944, 0xfd567e32, 0xfd204bb2, 0xc5330bcc, 0x5202894e,
+ 0xf9e309b0, 0x4cc17557, 0xdb9064ae, 0xe19e77d8, 0x25857f60, 0xeb4a15ad, 0x1f47f554, 0xea4472d9,
+ 0xd20de593, 0xf5733b25, 0x11892b54, 0x5729d35f, 0xe6188cd1, 0x488b132e, 0x541c534a, 0xa8e854ae,
+ 0xa255a66c, 0x33688763, 0xc6629ac6, 0xc20a6265, 0xcd92a059, 0x72029d3b, 0x4c298f5e, 0x51452e4e,
+ 0xbb065058, 0x15fd2dcc, 0xf40c135e, 0x615a0bad, 0x0c6a6805, 0x4971a7ad, 0x17f2a5d5, 0xf8babf47,
+ 0xb61f50ad, 0x4e1451b1, 0xf72d9252, 0x5c2abe58, 0xbd987c61, 0x084ae5cf, 0x20781fb0, 0x38b0f160,
+ 0x18aac705, 0x14f86dc1, 0x5556f481, 0x0a36c144, 0xeb446e4c, 0x2c1c0d6c, 0xbd0ff860, 0x869f92db,
+ 0x36c94f4c, 0x05502444, 0x148fe55b, 0xd5301e59, 0xd57a8f45, 0x110dc04a, 0x8670fc36, 0xee733b25,
+ 0xca56f481, 0x2a5c3bae, 0x844b0905, 0x1e51fe53, 0x0241c244, 0x59c0614e, 0x94e70a55, 0x7312fead,
+ 0xb735be44, 0xa55d0905, 0x2f63962e, 0x14a4e15b, 0x63f8f05c, 0x62d0d262, 0x3cab41ad, 0x87f1b1cb,
+ 0x018da6b8, 0xb3967dd5, 0xcb56f481, 0x685ad718, 0x3b4aeeca, 0x8d106bc1, 0x51180905, 0x72660f48,
+ 0x1521a243, 0x5b56f481, 0x6390e560, 0xdd61464e, 0x58353b25, 0x553fc062, 0x27c45d59, 0xacc62e4e,
+ 0x0d5a1cd9, 0x7f65f442, 0xbdeef660, 0xf1bd1855, 0xf8473cae, 0x13b120b2, 0x442440d0, 0x53fd4352,
+ 0xa305fc57, 0x458be84d, 0x639ce1c3, 0xebaaee47, 0x95e2c247, 0xf056f481, 0x6256f481, 0x1d87c65e,
+ 0x0a453418, 0x5beb175e, 0xd64f1618, 0xc360795b, 0x2fbf5753, 0xa8c58e53, 0x651cec52, 0x9d37b043,
+ 0x124a9758, 0x5242e4a9, 0x89913c6c, 0x880efe2e, 0x2f2f2f0c, 0x72b26751, 0x2896e46d, 0x80f4166c,
+ 0x320d59ad, 0xc50151d0, 0x11a8aa43, 0xccf56057, 0x5fbad118, 0x4719b151, 0x2b5f4bc0, 0x4d7a4a50,
+ 0xad06e047, 0x62ef5a46, 0x5aebde58, 0xdf7aa66c, 0x851acb50, 0x66b9a559, 0x3e9bb153, 0xcc512f2e,
+ 0xc073b08e, 0xd519be58, 0xe981ea4d, 0x12fd50cb, 0x378739ad, 0x06683cae, 0xa22310b2, 0xc185c705,
+ 0x8741b545, 0xa26c8318, 0x22d5bc43, 0x39201ec0, 0x68581e3e, 0xdc9bcf62, 0xd508cc82, 0xb149675b,
+ 0x4c9609b0, 0x84feb84c, 0x08291e2e, 0xfd2253b2, 0x1fd269c1, 0xc9483932, 0x4d641fb0, 0x7d37c918,
+ 0xa9de20ad, 0x77e2d655, 0x6d421b59, 0xd7668f80, 0xced09b62, 0xa9e5a5bc, 0xa4074e18, 0x60fc5ecc,
+ 0x01300148, 0x68062444, 0xb4224847, 0xed3aa443, 0xb772fb43, 0x9f56f481, 0x220dfd18, 0x8e1c3d6c,
+ 0xc44f09b0, 0x7df2bb73, 0xe22fb844, 0xea534242, 0xb6a755d4, 0xa036654b, 0x138ece5b, 0xda65d3c3,
+ 0x955871bc, 0x792124b0, 0xfc82594c, 0x851d494b, 0x2c7aee47, 0x26af46b8, 0x1416252e, 0xa8abb944,
+ 0x36c49d25, 0x674f645d, 0x363646b8, 0x9e1a2942, 0x66d0c154, 0xc6c2a545, 0x3570f2ad, 0xe7d547c7,
+ 0x7d104932, 0x18cb9c18, 0x1dcfa4cf, 0xd156f481, 0x2a02b91f, 0x3eeb3fa8, 0xcac4175e, 0x34146d42,
+ 0x994c4d46, 0x5666f440, 0x85d6713e, 0x5ecb296c, 0x0ea0ae46, 0x87e69f42, 0xc58409b0, 0x1f3436ae,
+ 0x21dc6a57, 0x4ad1cd42, 0xfb8c1a4c, 0x52d3dab2, 0x3769894b, 0xb52f1c62, 0x3677916d, 0x82b3fe57,
+ 0x493d4ac6, 0x9f963c6c, 0x5d91ff60, 0x458e0dad, 0xa49d0947, 0x491a3e18, 0x4aadcd5b, 0x0e46494b,
+ 0x1d1610ad, 0x1a10af5d, 0x4956f481, 0x207a3eae, 0x77e73244, 0xfa3b8742, 0x3261fc36, 0xfcebf536,
+ 0x1662e836, 0xf655f636, 0xa2dbd0ad, 0x23036693, 0x30448432, 0xa2b03463, 0x30730344, 0x8e4a6882,
+ 0x0c50a1cb, 0xc8d8c06b, 0xc9cd6191, 0xf443db50, 0xa9553c50, 0x23145847, 0xc35da66c, 0x29c12a60,
+ 0x55c2b447, 0x7434f75c, 0x61660640, 0xde2a7018, 0xc639494c, 0x1c306fce, 0x19b89244, 0xd29a6462,
+ 0x462cd1b2, 0x29902f44, 0x2817fa53, 0x21a30905, 0x7777ae46, 0x288443a1, 0x7bee5148, 0xc2a8b043,
+ 0xf5c3d35f, 0x2311ef84, 0x57de08a4, 0x6b221bb2, 0xf2625846, 0x4b9e09b0, 0xa24f880e, 0x22b11447,
+ 0xb3a0c744, 0x919e77d8, 0xec8b64ae, 0xff5c8d45, 0x7b15b484, 0x32679a5f, 0xba80b62e, 0x05c25c61,
+ 0x60014746, 0x5e8fb04c, 0xe67c0905, 0x4329c658, 0xac8fe555, 0xf875e647, 0x67406386, 0x35ceea18,
+ 0xbb79484b, 0xd7b9fa62, 0x238209b0, 0x208a1d32, 0x9630995e, 0x039c1318, 0x6e48006c, 0x60582344,
+ 0xadbb0150, 0x853fd462, 0x03772e4e, 0x652ce960, 0x49b630ad, 0x9993af43, 0x3735b34b, 0x548a07d9,
+ 0x55a44aad, 0xa23d1bcc, 0xfdbb2f4e, 0x530b24a0, 0x0a44b451, 0x6827c657, 0x1f66494b, 0x4e680a47,
+ 0x77e7b747, 0xa5eb3fa8, 0x6649764a, 0xd4e76c4b, 0x2c691fb0, 0xf1292e44, 0xc6d6c774, 0x85d23775,
+ 0x28275f4d, 0x259ae46d, 0x02424e81, 0x5f16be58, 0xe707c658, 0x49eae5c7, 0xd5d147ad, 0x9a7abdc3,
+ 0xe8ac7fc7, 0x84ec3aae, 0xc24942d0, 0x294aa318, 0x08ac3d18, 0x8894042e, 0xb24609b0, 0x9bcaab58,
+ 0xc400f712, 0xd5c512b8, 0x2c02cc62, 0x25080fd8, 0xed74a847, 0x18a5ec5e, 0x9850ec6d, 0xf8909758,
+ 0x7f56f481, 0x4496f23c, 0xae27784f, 0xcb7cd93e, 0x06e32860, 0x50b9a84f, 0x3660434a, 0x09161f5f,
+ 0x900486bc, 0x08055459, 0xe7ec1017, 0x7e39494c, 0x4f443b25, 0x14751a8a, 0x717d03d4, 0xbd0e24d8,
+ 0x054b6f56, 0x854c496c, 0xd92a454a, 0xc39bd054, 0x6093614b, 0x9dbad754, 0x5bf0604a, 0x99f22305
+};
+
+class CMainParams : public CChainParams {
+public:
+ CMainParams() {
+ // The message start string is designed to be unlikely to occur in normal data.
+ // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
+ // a large 4-byte int at any alignment.
+ pchMessageStart[0] = 0xf9;
+ pchMessageStart[1] = 0xbe;
+ pchMessageStart[2] = 0xb4;
+ pchMessageStart[3] = 0xd9;
+ vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
+ nDefaultPort = 8333;
+ nRPCPort = 8332;
+ bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
+ nSubsidyHalvingInterval = 210000;
+
+ // Build the genesis block. Note that the output of the genesis coinbase cannot
+ // be spent as it did not originally exist in the database.
+ //
+ // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
+ // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
+ // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
+ // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
+ // vMerkleTree: 4a5e1e
+ const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
+ CTransaction txNew;
+ txNew.vin.resize(1);
+ txNew.vout.resize(1);
+ txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
+ txNew.vout[0].nValue = 50 * COIN;
+ txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
+ genesis.vtx.push_back(txNew);
+ genesis.hashPrevBlock = 0;
+ genesis.hashMerkleRoot = genesis.BuildMerkleTree();
+ genesis.nVersion = 1;
+ genesis.nTime = 1231006505;
+ genesis.nBits = 0x1d00ffff;
+ genesis.nNonce = 2083236893;
+
+ hashGenesisBlock = genesis.GetHash();
+ assert(hashGenesisBlock == uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
+ assert(genesis.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
+
+ vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be"));
+ vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me"));
+ vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
+ vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
+
+ base58Prefixes[PUBKEY_ADDRESS] = 0;
+ base58Prefixes[SCRIPT_ADDRESS] = 5;
+ base58Prefixes[SECRET_KEY] = 128;
+
+ // Convert the pnSeeds array into usable address objects.
+ for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
+ {
+ // 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;
+ struct in_addr ip;
+ memcpy(&ip, &pnSeed[i], sizeof(ip));
+ CAddress addr(CService(ip, GetDefaultPort()));
+ addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
+ vFixedSeeds.push_back(addr);
+ }
+ }
+
+ virtual const CBlock& GenesisBlock() const { return genesis; }
+ virtual Network NetworkID() const { return CChainParams::MAIN; }
+
+ virtual const vector<CAddress>& FixedSeeds() const {
+ return vFixedSeeds;
+ }
+protected:
+ CBlock genesis;
+ vector<CAddress> vFixedSeeds;
+};
+static CMainParams mainParams;
+
+
+//
+// Testnet (v3)
+//
+class CTestNetParams : public CMainParams {
+public:
+ CTestNetParams() {
+ // The message start string is designed to be unlikely to occur in normal data.
+ // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
+ // a large 4-byte int at any alignment.
+ pchMessageStart[0] = 0x0b;
+ pchMessageStart[1] = 0x11;
+ pchMessageStart[2] = 0x09;
+ pchMessageStart[3] = 0x07;
+ vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
+ nDefaultPort = 18333;
+ nRPCPort = 18332;
+ strDataDir = "testnet3";
+
+ // Modify the testnet genesis block so the timestamp is valid for a later start.
+ genesis.nTime = 1296688602;
+ genesis.nNonce = 414098458;
+ hashGenesisBlock = genesis.GetHash();
+ assert(hashGenesisBlock == uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
+
+ vFixedSeeds.clear();
+ vSeeds.clear();
+ vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"));
+ vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
+
+ base58Prefixes[PUBKEY_ADDRESS] = 111;
+ base58Prefixes[SCRIPT_ADDRESS] = 196;
+ base58Prefixes[SECRET_KEY] = 239;
+
+ }
+ virtual Network NetworkID() const { return CChainParams::TESTNET; }
+};
+static CTestNetParams testNetParams;
+
+
+//
+// Regression test
+//
+class CRegTestParams : public CTestNetParams {
+public:
+ CRegTestParams() {
+ pchMessageStart[0] = 0xfa;
+ pchMessageStart[1] = 0xbf;
+ pchMessageStart[2] = 0xb5;
+ pchMessageStart[3] = 0xda;
+ nSubsidyHalvingInterval = 150;
+ bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
+ genesis.nTime = 1296688602;
+ genesis.nBits = 0x207fffff;
+ genesis.nNonce = 2;
+ hashGenesisBlock = genesis.GetHash();
+ nDefaultPort = 18444;
+ strDataDir = "regtest";
+ assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
+
+ vSeeds.clear(); // Regtest mode doesn't have any DNS seeds.
+
+ base58Prefixes[PUBKEY_ADDRESS] = 0;
+ base58Prefixes[SCRIPT_ADDRESS] = 5;
+ base58Prefixes[SECRET_KEY] = 128;
+ }
+
+ virtual bool RequireRPCPassword() const { return false; }
+ virtual Network NetworkID() const { return CChainParams::REGTEST; }
+};
+static CRegTestParams regTestParams;
+
+static CChainParams *pCurrentParams = &mainParams;
+
+const CChainParams &Params() {
+ return *pCurrentParams;
+}
+
+void SelectParams(CChainParams::Network network) {
+ switch (network) {
+ case CChainParams::MAIN:
+ pCurrentParams = &mainParams;
+ break;
+ case CChainParams::TESTNET:
+ pCurrentParams = &testNetParams;
+ break;
+ case CChainParams::REGTEST:
+ pCurrentParams = &regTestParams;
+ break;
+ default:
+ assert(false && "Unimplemented network");
+ return;
+ }
+}
+
+bool SelectParamsFromCommandLine() {
+ bool fRegTest = GetBoolArg("-regtest", false);
+ bool fTestNet = GetBoolArg("-testnet", false);
+
+ if (fTestNet && fRegTest) {
+ return false;
+ }
+
+ if (fRegTest) {
+ SelectParams(CChainParams::REGTEST);
+ } else if (fTestNet) {
+ SelectParams(CChainParams::TESTNET);
+ } else {
+ SelectParams(CChainParams::MAIN);
+ }
+ return true;
+}
diff --git a/src/chainparams.h b/src/chainparams.h
new file mode 100644
index 0000000000..572712b589
--- /dev/null
+++ b/src/chainparams.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CHAIN_PARAMS_H
+#define BITCOIN_CHAIN_PARAMS_H
+
+#include "bignum.h"
+#include "uint256.h"
+#include "util.h"
+
+#include <vector>
+
+using namespace std;
+
+#define MESSAGE_START_SIZE 4
+typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
+
+class CAddress;
+class CBlock;
+
+struct CDNSSeedData {
+ string name, host;
+ CDNSSeedData(const string &strName, const string &strHost) : name(strName), host(strHost) {}
+};
+
+/**
+ * CChainParams defines various tweakable parameters of a given instance of the
+ * Bitcoin system. There are three: the main network on which people trade goods
+ * and services, the public test network which gets reset from time to time and
+ * a regression test mode which is intended for private networks only. It has
+ * minimal difficulty to ensure that blocks can be found instantly.
+ */
+class CChainParams
+{
+public:
+ enum Network {
+ MAIN,
+ TESTNET,
+ REGTEST,
+ };
+
+ enum Base58Type {
+ PUBKEY_ADDRESS,
+ SCRIPT_ADDRESS,
+ SECRET_KEY,
+
+ MAX_BASE58_TYPES
+ };
+
+ const uint256& HashGenesisBlock() const { return hashGenesisBlock; }
+ const MessageStartChars& MessageStart() const { return pchMessageStart; }
+ const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
+ int GetDefaultPort() const { return nDefaultPort; }
+ const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
+ int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
+ virtual const CBlock& GenesisBlock() const = 0;
+ virtual bool RequireRPCPassword() const { return true; }
+ const string& DataDir() const { return strDataDir; }
+ virtual Network NetworkID() const = 0;
+ const vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
+ int Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
+ virtual const vector<CAddress>& FixedSeeds() const = 0;
+ int RPCPort() const { return nRPCPort; }
+protected:
+ CChainParams() {};
+
+ uint256 hashGenesisBlock;
+ MessageStartChars pchMessageStart;
+ // Raw pub key bytes for the broadcast alert signing key.
+ vector<unsigned char> vAlertPubKey;
+ int nDefaultPort;
+ int nRPCPort;
+ CBigNum bnProofOfWorkLimit;
+ int nSubsidyHalvingInterval;
+ string strDataDir;
+ vector<CDNSSeedData> vSeeds;
+ int base58Prefixes[MAX_BASE58_TYPES];
+};
+
+/**
+ * Return the currently selected parameters. This won't change after app startup
+ * outside of the unit tests.
+ */
+const CChainParams &Params();
+
+/** Sets the params returned by Params() to those for the given network. */
+void SelectParams(CChainParams::Network network);
+
+/**
+ * Looks for -regtest or -testnet and then calls SelectParams as appropriate.
+ * Returns false if an invalid combination is given.
+ */
+bool SelectParamsFromCommandLine();
+
+inline bool TestNet() {
+ // Note: it's deliberate that this returns "false" for regression test mode.
+ return Params().NetworkID() == CChainParams::TESTNET;
+}
+
+#endif
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 9e8e0f7024..ba29e2463e 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -28,6 +28,8 @@ namespace Checkpoints
double fTransactionsPerDay;
};
+ bool fEnabled = true;
+
// What makes a good checkpoint block?
// + Is surrounded by blocks with reasonable timestamps
// (no blocks before with a timestamp after, none after with
@@ -54,7 +56,7 @@ namespace Checkpoints
60000.0 // * estimated number of transactions per day after checkpoint
};
- static MapCheckpoints mapCheckpointsTestnet =
+ static MapCheckpoints mapCheckpointsTestnet =
boost::assign::map_list_of
( 546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"))
;
@@ -66,7 +68,7 @@ namespace Checkpoints
};
const CCheckpointData &Checkpoints() {
- if (fTestNet)
+ if (TestNet())
return dataTestnet;
else
return data;
@@ -74,7 +76,7 @@ namespace Checkpoints
bool CheckBlock(int nHeight, const uint256& hash)
{
- if (!GetBoolArg("-checkpoints", true))
+ if (!fEnabled)
return true;
const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;
@@ -117,7 +119,7 @@ namespace Checkpoints
int GetTotalBlocksEstimate()
{
- if (!GetBoolArg("-checkpoints", true))
+ if (!fEnabled)
return 0;
const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;
@@ -127,7 +129,7 @@ namespace Checkpoints
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
{
- if (!GetBoolArg("-checkpoints", true))
+ if (!fEnabled)
return NULL;
const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 3d56885556..a49a908a38 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -24,6 +24,8 @@ namespace Checkpoints
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
double GuessVerificationProgress(CBlockIndex *pindex);
+
+ extern bool fEnabled;
}
#endif
diff --git a/src/clientversion.h b/src/clientversion.h
index d6ca03a725..30c0c4072b 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MINOR 8
-#define CLIENT_VERSION_REVISION 2
+#define CLIENT_VERSION_REVISION 99
#define CLIENT_VERSION_BUILD 0
// Set to true for release, false for prerelease or test build
diff --git a/src/core.cpp b/src/core.cpp
new file mode 100644
index 0000000000..b12c90efe8
--- /dev/null
+++ b/src/core.cpp
@@ -0,0 +1,7 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "core.h"
+
diff --git a/src/core.h b/src/core.h
new file mode 100644
index 0000000000..fce9ccc162
--- /dev/null
+++ b/src/core.h
@@ -0,0 +1,859 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_CORE_H
+#define BITCOIN_CORE_H
+
+#include "uint256.h"
+#include "serialize.h"
+#include "util.h"
+#include "script.h"
+
+#include <stdio.h>
+
+class CTransaction;
+
+/** An outpoint - a combination of a transaction hash and an index n into its vout */
+class COutPoint
+{
+public:
+ uint256 hash;
+ unsigned int n;
+
+ COutPoint() { SetNull(); }
+ COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
+ IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
+ void SetNull() { hash = 0; n = (unsigned int) -1; }
+ bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
+
+ friend bool operator<(const COutPoint& a, const COutPoint& b)
+ {
+ return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
+ }
+
+ friend bool operator==(const COutPoint& a, const COutPoint& b)
+ {
+ return (a.hash == b.hash && a.n == b.n);
+ }
+
+ friend bool operator!=(const COutPoint& a, const COutPoint& b)
+ {
+ return !(a == b);
+ }
+
+ std::string ToString() const
+ {
+ return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n);
+ }
+
+ void print() const
+ {
+ printf("%s\n", ToString().c_str());
+ }
+};
+
+/** An inpoint - a combination of a transaction and an index n into its vin */
+class CInPoint
+{
+public:
+ CTransaction* ptx;
+ unsigned int n;
+
+ CInPoint() { SetNull(); }
+ CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
+ void SetNull() { ptx = NULL; n = (unsigned int) -1; }
+ bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
+};
+
+/** An input of a transaction. It contains the location of the previous
+ * transaction's output that it claims and a signature that matches the
+ * output's public key.
+ */
+class CTxIn
+{
+public:
+ COutPoint prevout;
+ CScript scriptSig;
+ unsigned int nSequence;
+
+ CTxIn()
+ {
+ nSequence = std::numeric_limits<unsigned int>::max();
+ }
+
+ explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
+ {
+ prevout = prevoutIn;
+ scriptSig = scriptSigIn;
+ nSequence = nSequenceIn;
+ }
+
+ CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
+ {
+ prevout = COutPoint(hashPrevTx, nOut);
+ scriptSig = scriptSigIn;
+ nSequence = nSequenceIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(prevout);
+ READWRITE(scriptSig);
+ READWRITE(nSequence);
+ )
+
+ bool IsFinal() const
+ {
+ return (nSequence == std::numeric_limits<unsigned int>::max());
+ }
+
+ friend bool operator==(const CTxIn& a, const CTxIn& b)
+ {
+ return (a.prevout == b.prevout &&
+ a.scriptSig == b.scriptSig &&
+ a.nSequence == b.nSequence);
+ }
+
+ friend bool operator!=(const CTxIn& a, const CTxIn& b)
+ {
+ return !(a == b);
+ }
+
+ std::string ToString() const
+ {
+ std::string str;
+ str += "CTxIn(";
+ str += prevout.ToString();
+ if (prevout.IsNull())
+ str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
+ else
+ str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
+ if (nSequence != std::numeric_limits<unsigned int>::max())
+ str += strprintf(", nSequence=%u", nSequence);
+ str += ")";
+ return str;
+ }
+
+ void print() const
+ {
+ printf("%s\n", ToString().c_str());
+ }
+};
+
+
+
+
+/** An output of a transaction. It contains the public key that the next input
+ * must be able to sign with to claim it.
+ */
+class CTxOut
+{
+public:
+ int64 nValue;
+ CScript scriptPubKey;
+
+ CTxOut()
+ {
+ SetNull();
+ }
+
+ CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
+ {
+ nValue = nValueIn;
+ scriptPubKey = scriptPubKeyIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(nValue);
+ READWRITE(scriptPubKey);
+ )
+
+ void SetNull()
+ {
+ nValue = -1;
+ scriptPubKey.clear();
+ }
+
+ bool IsNull() const
+ {
+ return (nValue == -1);
+ }
+
+ uint256 GetHash() const
+ {
+ return SerializeHash(*this);
+ }
+
+ bool IsDust(int64 nMinRelayTxFee) const
+ {
+ // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
+ // which has units satoshis-per-kilobyte.
+ // If you'd pay more than 1/3 in fees
+ // to spend something, then we consider it dust.
+ // A typical txout is 34 bytes big, and will
+ // need a CTxIn of at least 148 bytes to spend,
+ // so dust is a txout less than 54 uBTC
+ // (5460 satoshis) with default nMinRelayTxFee
+ return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
+ }
+
+ friend bool operator==(const CTxOut& a, const CTxOut& b)
+ {
+ return (a.nValue == b.nValue &&
+ a.scriptPubKey == b.scriptPubKey);
+ }
+
+ friend bool operator!=(const CTxOut& a, const CTxOut& b)
+ {
+ return !(a == b);
+ }
+
+ std::string ToString() const
+ {
+ if (scriptPubKey.size() < 6)
+ return "CTxOut(error)";
+ return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
+ }
+
+ void print() const
+ {
+ printf("%s\n", ToString().c_str());
+ }
+};
+
+
+/** The basic transaction that is broadcasted on the network and contained in
+ * blocks. A transaction can contain multiple inputs and outputs.
+ */
+class CTransaction
+{
+public:
+ static int64 nMinTxFee;
+ static int64 nMinRelayTxFee;
+ static const int CURRENT_VERSION=1;
+ int nVersion;
+ std::vector<CTxIn> vin;
+ std::vector<CTxOut> vout;
+ unsigned int nLockTime;
+
+ CTransaction()
+ {
+ SetNull();
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(vin);
+ READWRITE(vout);
+ READWRITE(nLockTime);
+ )
+
+ void SetNull()
+ {
+ nVersion = CTransaction::CURRENT_VERSION;
+ vin.clear();
+ vout.clear();
+ nLockTime = 0;
+ }
+
+ bool IsNull() const
+ {
+ return (vin.empty() && vout.empty());
+ }
+
+ uint256 GetHash() const
+ {
+ return SerializeHash(*this);
+ }
+
+ bool IsNewerThan(const CTransaction& old) const
+ {
+ if (vin.size() != old.vin.size())
+ return false;
+ for (unsigned int i = 0; i < vin.size(); i++)
+ if (vin[i].prevout != old.vin[i].prevout)
+ return false;
+
+ bool fNewer = false;
+ unsigned int nLowest = std::numeric_limits<unsigned int>::max();
+ for (unsigned int i = 0; i < vin.size(); i++)
+ {
+ if (vin[i].nSequence != old.vin[i].nSequence)
+ {
+ if (vin[i].nSequence <= nLowest)
+ {
+ fNewer = false;
+ nLowest = vin[i].nSequence;
+ }
+ if (old.vin[i].nSequence < nLowest)
+ {
+ fNewer = true;
+ nLowest = old.vin[i].nSequence;
+ }
+ }
+ }
+ return fNewer;
+ }
+
+ bool IsCoinBase() const
+ {
+ return (vin.size() == 1 && vin[0].prevout.IsNull());
+ }
+
+ friend bool operator==(const CTransaction& a, const CTransaction& b)
+ {
+ return (a.nVersion == b.nVersion &&
+ a.vin == b.vin &&
+ a.vout == b.vout &&
+ a.nLockTime == b.nLockTime);
+ }
+
+ friend bool operator!=(const CTransaction& a, const CTransaction& b)
+ {
+ return !(a == b);
+ }
+
+
+ std::string ToString() const
+ {
+ std::string str;
+ str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
+ GetHash().ToString().substr(0,10).c_str(),
+ nVersion,
+ vin.size(),
+ vout.size(),
+ nLockTime);
+ for (unsigned int i = 0; i < vin.size(); i++)
+ str += " " + vin[i].ToString() + "\n";
+ for (unsigned int i = 0; i < vout.size(); i++)
+ str += " " + vout[i].ToString() + "\n";
+ return str;
+ }
+
+ void print() const
+ {
+ printf("%s", ToString().c_str());
+ }
+};
+
+/** wrapper for CTxOut that provides a more compact serialization */
+class CTxOutCompressor
+{
+private:
+ CTxOut &txout;
+
+public:
+ static uint64 CompressAmount(uint64 nAmount);
+ static uint64 DecompressAmount(uint64 nAmount);
+
+ CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
+
+ IMPLEMENT_SERIALIZE(({
+ if (!fRead) {
+ uint64 nVal = CompressAmount(txout.nValue);
+ READWRITE(VARINT(nVal));
+ } else {
+ uint64 nVal = 0;
+ READWRITE(VARINT(nVal));
+ txout.nValue = DecompressAmount(nVal);
+ }
+ CScriptCompressor cscript(REF(txout.scriptPubKey));
+ READWRITE(cscript);
+ });)
+};
+
+/** Undo information for a CTxIn
+ *
+ * Contains the prevout's CTxOut being spent, and if this was the
+ * last output of the affected transaction, its metadata as well
+ * (coinbase or not, height, transaction version)
+ */
+class CTxInUndo
+{
+public:
+ CTxOut txout; // the txout data before being spent
+ bool fCoinBase; // if the outpoint was the last unspent: whether it belonged to a coinbase
+ unsigned int nHeight; // if the outpoint was the last unspent: its height
+ int nVersion; // if the outpoint was the last unspent: its version
+
+ CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nVersion(0) {}
+ CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, unsigned int nHeightIn = 0, int nVersionIn = 0) : txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nVersion(nVersionIn) { }
+
+ unsigned int GetSerializeSize(int nType, int nVersion) const {
+ return ::GetSerializeSize(VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion) +
+ (nHeight > 0 ? ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion) : 0) +
+ ::GetSerializeSize(CTxOutCompressor(REF(txout)), nType, nVersion);
+ }
+
+ template<typename Stream>
+ void Serialize(Stream &s, int nType, int nVersion) const {
+ ::Serialize(s, VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion);
+ if (nHeight > 0)
+ ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
+ ::Serialize(s, CTxOutCompressor(REF(txout)), nType, nVersion);
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream &s, int nType, int nVersion) {
+ unsigned int nCode = 0;
+ ::Unserialize(s, VARINT(nCode), nType, nVersion);
+ nHeight = nCode / 2;
+ fCoinBase = nCode & 1;
+ if (nHeight > 0)
+ ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
+ ::Unserialize(s, REF(CTxOutCompressor(REF(txout))), nType, nVersion);
+ }
+};
+
+/** Undo information for a CTransaction */
+class CTxUndo
+{
+public:
+ // undo information for all txins
+ std::vector<CTxInUndo> vprevout;
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(vprevout);
+ )
+};
+
+
+/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
+ *
+ * Serialized format:
+ * - VARINT(nVersion)
+ * - VARINT(nCode)
+ * - unspentness bitvector, for vout[2] and further; least significant byte first
+ * - the non-spent CTxOuts (via CTxOutCompressor)
+ * - VARINT(nHeight)
+ *
+ * The nCode value consists of:
+ * - bit 1: IsCoinBase()
+ * - bit 2: vout[0] is not spent
+ * - bit 4: vout[1] is not spent
+ * - The higher bits encode N, the number of non-zero bytes in the following bitvector.
+ * - In case both bit 2 and bit 4 are unset, they encode N-1, as there must be at
+ * least one non-spent output).
+ *
+ * Example: 0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e
+ * <><><--------------------------------------------><---->
+ * | \ | /
+ * version code vout[1] height
+ *
+ * - version = 1
+ * - code = 4 (vout[1] is not spent, and 0 non-zero bytes of bitvector follow)
+ * - unspentness bitvector: as 0 non-zero bytes follow, it has length 0
+ * - vout[1]: 835800816115944e077fe7c803cfa57f29b36bf87c1d35
+ * * 8358: compact amount representation for 60000000000 (600 BTC)
+ * * 00: special txout type pay-to-pubkey-hash
+ * * 816115944e077fe7c803cfa57f29b36bf87c1d35: address uint160
+ * - height = 203998
+ *
+ *
+ * Example: 0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b
+ * <><><--><--------------------------------------------------><----------------------------------------------><---->
+ * / \ \ | | /
+ * version code unspentness vout[4] vout[16] height
+ *
+ * - version = 1
+ * - code = 9 (coinbase, neither vout[0] or vout[1] are unspent,
+ * 2 (1, +1 because both bit 2 and bit 4 are unset) non-zero bitvector bytes follow)
+ * - unspentness bitvector: bits 2 (0x04) and 14 (0x4000) are set, so vout[2+2] and vout[14+2] are unspent
+ * - vout[4]: 86ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4ee
+ * * 86ef97d579: compact amount representation for 234925952 (2.35 BTC)
+ * * 00: special txout type pay-to-pubkey-hash
+ * * 61b01caab50f1b8e9c50a5057eb43c2d9563a4ee: address uint160
+ * - vout[16]: bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4
+ * * bbd123: compact amount representation for 110397 (0.001 BTC)
+ * * 00: special txout type pay-to-pubkey-hash
+ * * 8c988f1a4a4de2161e0f50aac7f17e7f9555caa4: address uint160
+ * - height = 120891
+ */
+class CCoins
+{
+public:
+ // whether transaction is a coinbase
+ bool fCoinBase;
+
+ // unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
+ std::vector<CTxOut> vout;
+
+ // at which height this transaction was included in the active block chain
+ int nHeight;
+
+ // version of the CTransaction; accesses to this value should probably check for nHeight as well,
+ // as new tx version will probably only be introduced at certain heights
+ int nVersion;
+
+ // construct a CCoins from a CTransaction, at a given height
+ CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) { }
+
+ // empty constructor
+ CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
+
+ // remove spent outputs at the end of vout
+ void Cleanup() {
+ while (vout.size() > 0 && vout.back().IsNull())
+ vout.pop_back();
+ if (vout.empty())
+ std::vector<CTxOut>().swap(vout);
+ }
+
+ void swap(CCoins &to) {
+ std::swap(to.fCoinBase, fCoinBase);
+ to.vout.swap(vout);
+ std::swap(to.nHeight, nHeight);
+ std::swap(to.nVersion, nVersion);
+ }
+
+ // equality test
+ friend bool operator==(const CCoins &a, const CCoins &b) {
+ return a.fCoinBase == b.fCoinBase &&
+ a.nHeight == b.nHeight &&
+ a.nVersion == b.nVersion &&
+ a.vout == b.vout;
+ }
+ friend bool operator!=(const CCoins &a, const CCoins &b) {
+ return !(a == b);
+ }
+
+ // calculate number of bytes for the bitmask, and its number of non-zero bytes
+ // each bit in the bitmask represents the availability of one output, but the
+ // availabilities of the first two outputs are encoded separately
+ void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
+ unsigned int nLastUsedByte = 0;
+ for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
+ bool fZero = true;
+ for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
+ if (!vout[2+b*8+i].IsNull()) {
+ fZero = false;
+ continue;
+ }
+ }
+ if (!fZero) {
+ nLastUsedByte = b + 1;
+ nNonzeroBytes++;
+ }
+ }
+ nBytes += nLastUsedByte;
+ }
+
+ bool IsCoinBase() const {
+ return fCoinBase;
+ }
+
+ unsigned int GetSerializeSize(int nType, int nVersion) const {
+ unsigned int nSize = 0;
+ unsigned int nMaskSize = 0, nMaskCode = 0;
+ CalcMaskSize(nMaskSize, nMaskCode);
+ bool fFirst = vout.size() > 0 && !vout[0].IsNull();
+ bool fSecond = vout.size() > 1 && !vout[1].IsNull();
+ assert(fFirst || fSecond || nMaskCode);
+ unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
+ // version
+ nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion);
+ // size of header code
+ nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion);
+ // spentness bitmask
+ nSize += nMaskSize;
+ // txouts themself
+ for (unsigned int i = 0; i < vout.size(); i++)
+ if (!vout[i].IsNull())
+ nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion);
+ // height
+ nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion);
+ return nSize;
+ }
+
+ template<typename Stream>
+ void Serialize(Stream &s, int nType, int nVersion) const {
+ unsigned int nMaskSize = 0, nMaskCode = 0;
+ CalcMaskSize(nMaskSize, nMaskCode);
+ bool fFirst = vout.size() > 0 && !vout[0].IsNull();
+ bool fSecond = vout.size() > 1 && !vout[1].IsNull();
+ assert(fFirst || fSecond || nMaskCode);
+ unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
+ // version
+ ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
+ // header code
+ ::Serialize(s, VARINT(nCode), nType, nVersion);
+ // spentness bitmask
+ for (unsigned int b = 0; b<nMaskSize; b++) {
+ unsigned char chAvail = 0;
+ for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++)
+ if (!vout[2+b*8+i].IsNull())
+ chAvail |= (1 << i);
+ ::Serialize(s, chAvail, nType, nVersion);
+ }
+ // txouts themself
+ for (unsigned int i = 0; i < vout.size(); i++) {
+ if (!vout[i].IsNull())
+ ::Serialize(s, CTxOutCompressor(REF(vout[i])), nType, nVersion);
+ }
+ // coinbase height
+ ::Serialize(s, VARINT(nHeight), nType, nVersion);
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream &s, int nType, int nVersion) {
+ unsigned int nCode = 0;
+ // version
+ ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
+ // header code
+ ::Unserialize(s, VARINT(nCode), nType, nVersion);
+ fCoinBase = nCode & 1;
+ std::vector<bool> vAvail(2, false);
+ vAvail[0] = nCode & 2;
+ vAvail[1] = nCode & 4;
+ unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
+ // spentness bitmask
+ while (nMaskCode > 0) {
+ unsigned char chAvail = 0;
+ ::Unserialize(s, chAvail, nType, nVersion);
+ for (unsigned int p = 0; p < 8; p++) {
+ bool f = (chAvail & (1 << p)) != 0;
+ vAvail.push_back(f);
+ }
+ if (chAvail != 0)
+ nMaskCode--;
+ }
+ // txouts themself
+ vout.assign(vAvail.size(), CTxOut());
+ for (unsigned int i = 0; i < vAvail.size(); i++) {
+ if (vAvail[i])
+ ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion);
+ }
+ // coinbase height
+ ::Unserialize(s, VARINT(nHeight), nType, nVersion);
+ Cleanup();
+ }
+
+ // mark an outpoint spent, and construct undo information
+ bool Spend(const COutPoint &out, CTxInUndo &undo) {
+ if (out.n >= vout.size())
+ return false;
+ if (vout[out.n].IsNull())
+ return false;
+ undo = CTxInUndo(vout[out.n]);
+ vout[out.n].SetNull();
+ Cleanup();
+ if (vout.size() == 0) {
+ undo.nHeight = nHeight;
+ undo.fCoinBase = fCoinBase;
+ undo.nVersion = this->nVersion;
+ }
+ return true;
+ }
+
+ // mark a vout spent
+ bool Spend(int nPos) {
+ CTxInUndo undo;
+ COutPoint out(0, nPos);
+ return Spend(out, undo);
+ }
+
+ // check whether a particular output is still available
+ bool IsAvailable(unsigned int nPos) const {
+ return (nPos < vout.size() && !vout[nPos].IsNull());
+ }
+
+ // check whether the entire CCoins is spent
+ // note that only !IsPruned() CCoins can be serialized
+ bool IsPruned() const {
+ BOOST_FOREACH(const CTxOut &out, vout)
+ if (!out.IsNull())
+ return false;
+ return true;
+ }
+};
+
+
+/** Nodes collect new transactions into a block, hash them into a hash tree,
+ * and scan through nonce values to make the block's hash satisfy proof-of-work
+ * requirements. When they solve the proof-of-work, they broadcast the block
+ * to everyone and the block is added to the block chain. The first transaction
+ * in the block is a special one that creates a new coin owned by the creator
+ * of the block.
+ */
+class CBlockHeader
+{
+public:
+ // header
+ static const int CURRENT_VERSION=2;
+ int nVersion;
+ uint256 hashPrevBlock;
+ uint256 hashMerkleRoot;
+ unsigned int nTime;
+ unsigned int nBits;
+ unsigned int nNonce;
+
+ CBlockHeader()
+ {
+ SetNull();
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(hashPrevBlock);
+ READWRITE(hashMerkleRoot);
+ READWRITE(nTime);
+ READWRITE(nBits);
+ READWRITE(nNonce);
+ )
+
+ void SetNull()
+ {
+ nVersion = CBlockHeader::CURRENT_VERSION;
+ hashPrevBlock = 0;
+ hashMerkleRoot = 0;
+ nTime = 0;
+ nBits = 0;
+ nNonce = 0;
+ }
+
+ bool IsNull() const
+ {
+ return (nBits == 0);
+ }
+
+ uint256 GetHash() const
+ {
+ return Hash(BEGIN(nVersion), END(nNonce));
+ }
+
+ int64 GetBlockTime() const
+ {
+ return (int64)nTime;
+ }
+};
+
+
+class CBlock : public CBlockHeader
+{
+public:
+ // network and disk
+ std::vector<CTransaction> vtx;
+
+ // memory only
+ mutable std::vector<uint256> vMerkleTree;
+
+ CBlock()
+ {
+ SetNull();
+ }
+
+ CBlock(const CBlockHeader &header)
+ {
+ SetNull();
+ *((CBlockHeader*)this) = header;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(*(CBlockHeader*)this);
+ READWRITE(vtx);
+ )
+
+ void SetNull()
+ {
+ CBlockHeader::SetNull();
+ vtx.clear();
+ vMerkleTree.clear();
+ }
+
+ CBlockHeader GetBlockHeader() const
+ {
+ CBlockHeader block;
+ block.nVersion = nVersion;
+ block.hashPrevBlock = hashPrevBlock;
+ block.hashMerkleRoot = hashMerkleRoot;
+ block.nTime = nTime;
+ block.nBits = nBits;
+ block.nNonce = nNonce;
+ return block;
+ }
+
+ uint256 BuildMerkleTree() const
+ {
+ vMerkleTree.clear();
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ vMerkleTree.push_back(tx.GetHash());
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ for (int i = 0; i < nSize; i += 2)
+ {
+ int i2 = std::min(i+1, nSize-1);
+ vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
+ BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
+ }
+ j += nSize;
+ }
+ return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
+ }
+
+ const uint256 &GetTxHash(unsigned int nIndex) const {
+ assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
+ assert(nIndex < vtx.size());
+ return vMerkleTree[nIndex];
+ }
+
+ std::vector<uint256> GetMerkleBranch(int nIndex) const
+ {
+ if (vMerkleTree.empty())
+ BuildMerkleTree();
+ std::vector<uint256> vMerkleBranch;
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ int i = std::min(nIndex^1, nSize-1);
+ vMerkleBranch.push_back(vMerkleTree[j+i]);
+ nIndex >>= 1;
+ j += nSize;
+ }
+ return vMerkleBranch;
+ }
+
+ static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
+ {
+ if (nIndex == -1)
+ return 0;
+ BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
+ {
+ if (nIndex & 1)
+ hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
+ else
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
+ nIndex >>= 1;
+ }
+ return hash;
+ }
+
+ void print() const
+ {
+ printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
+ GetHash().ToString().c_str(),
+ nVersion,
+ hashPrevBlock.ToString().c_str(),
+ hashMerkleRoot.ToString().c_str(),
+ nTime, nBits, nNonce,
+ vtx.size());
+ for (unsigned int i = 0; i < vtx.size(); i++)
+ {
+ printf(" ");
+ vtx[i].print();
+ }
+ printf(" vMerkleTree: ");
+ for (unsigned int i = 0; i < vMerkleTree.size(); i++)
+ printf("%s ", vMerkleTree[i].ToString().c_str());
+ printf("\n");
+ }
+};
+
+#endif
diff --git a/src/crypter.cpp b/src/crypter.cpp
index a2b62a87c8..32baabd674 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -100,17 +100,17 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
}
-bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
+bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE);
if(!cKeyCrypter.SetKey(vMasterKey, chIV))
return false;
- return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext);
+ return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
}
-bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext)
+bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
{
CCrypter cKeyCrypter;
std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE);
diff --git a/src/crypter.h b/src/crypter.h
index 6f75170bac..4134c1b49b 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -101,7 +101,7 @@ public:
}
};
-bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
-bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char> &vchCiphertext, const uint256& nIV, CSecret &vchPlaintext);
+bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
+bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
#endif
diff --git a/src/db.cpp b/src/db.cpp
index 3133d99bf8..93f3f5d8c4 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -3,12 +3,15 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "db.h"
#include "util.h"
-#include "main.h"
+#include "hash.h"
+#include "addrman.h"
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
+#include <openssl/rand.h>
#ifndef WIN32
#include "sys/stat.h"
@@ -486,7 +489,6 @@ void CDBEnv::Flush(bool fShutdown)
// CAddrDB
//
-
CAddrDB::CAddrDB()
{
pathAddr = GetDataDir() / "peers.dat";
@@ -501,7 +503,7 @@ bool CAddrDB::Write(const CAddrMan& addr)
// serialize addresses, checksum data up to that point, then append csum
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
- ssPeers << FLATDATA(pchMessageStart);
+ ssPeers << FLATDATA(Params().MessageStart());
ssPeers << addr;
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
ssPeers << hash;
@@ -541,6 +543,8 @@ bool CAddrDB::Read(CAddrMan& addr)
// use file size to size memory buffer
int fileSize = GetFilesize(filein);
int dataSize = fileSize - sizeof(uint256);
+ //Don't try to resize to a negative number if file is small
+ if ( dataSize < 0 ) dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
uint256 hashIn;
@@ -564,11 +568,11 @@ bool CAddrDB::Read(CAddrMan& addr)
unsigned char pchMsgTmp[4];
try {
- // de-serialize file header (pchMessageStart magic number) and
+ // de-serialize file header (network specific magic number) and ..
ssPeers >> FLATDATA(pchMsgTmp);
- // verify the network matches ours
- if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
+ // ... verify the network matches ours
+ if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("CAddrman::Read() : invalid network magic number");
// de-serialize address data into one CAddrMan object
diff --git a/src/db.h b/src/db.h
index ea440c4960..b3f269f3da 100644
--- a/src/db.h
+++ b/src/db.h
@@ -5,22 +5,22 @@
#ifndef BITCOIN_DB_H
#define BITCOIN_DB_H
-#include "main.h"
+#include "sync.h"
+#include "serialize.h"
#include <map>
#include <string>
#include <vector>
+#include <boost/filesystem.hpp>
#include <db_cxx.h>
-class CAddress;
class CAddrMan;
class CBlockLocator;
class CDiskBlockIndex;
class CMasterKey;
class COutPoint;
class CWallet;
-class CWalletTx;
extern unsigned int nWalletDBUpdated;
diff --git a/src/hash.h b/src/hash.h
index eaa1780c04..536ab71165 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -105,15 +105,22 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
return ss.GetHash();
}
-inline uint160 Hash160(const std::vector<unsigned char>& vch)
+template<typename T1>
+inline uint160 Hash160(const T1 pbegin, const T1 pend)
{
+ static unsigned char pblank[1];
uint256 hash1;
- SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
+ SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
uint160 hash2;
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
return hash2;
}
+inline uint160 Hash160(const std::vector<unsigned char>& vch)
+{
+ return Hash160(vch.begin(), vch.end());
+}
+
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
#endif
diff --git a/src/init.cpp b/src/init.cpp
index d619cb4121..e88055bdea 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -3,13 +3,17 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "init.h"
+#include "main.h"
+#include "core.h"
+#include "chainparams.h"
#include "txdb.h"
#include "walletdb.h"
#include "bitcoinrpc.h"
#include "net.h"
-#include "init.h"
#include "util.h"
#include "ui_interface.h"
+#include "checkpoints.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -44,6 +48,7 @@ enum BindFlags {
BF_REPORT_ERROR = (1U << 1)
};
+
//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
@@ -96,10 +101,14 @@ void Shutdown()
RenameThread("bitcoin-shutoff");
nTransactionsUpdated++;
StopRPCThreads();
+ ShutdownRPCMining();
bitdb.Flush(false);
+ GenerateBitcoins(false, NULL);
StopNode();
{
LOCK(cs_main);
+ if (pwalletMain)
+ pwalletMain->SetBestChain(CBlockLocator(pindexBest));
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
@@ -117,17 +126,6 @@ void Shutdown()
//
// Signal handlers are very limited in what they are allowed to do, so:
//
-void DetectShutdownThread(boost::thread_group* threadGroup)
-{
- // Tell the main threads to shutdown.
- while (!fRequestShutdown)
- {
- MilliSleep(200);
- if (fRequestShutdown)
- threadGroup->interrupt_all();
- }
-}
-
void HandleSIGTERM(int)
{
fRequestShutdown = true;
@@ -138,127 +136,6 @@ void HandleSIGHUP(int)
fReopenDebugLog = true;
}
-
-
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Start
-//
-#if !defined(QT_GUI)
-bool AppInit(int argc, char* argv[])
-{
- boost::thread_group threadGroup;
- boost::thread* detectShutdownThread = NULL;
-
- bool fRet = false;
- try
- {
- //
- // Parameters
- //
- // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
- ParseParameters(argc, argv);
- if (!boost::filesystem::is_directory(GetDataDir(false)))
- {
- fprintf(stderr, "Error: Specified directory does not exist\n");
- Shutdown();
- }
- ReadConfigFile(mapArgs, mapMultiArgs);
-
- if (mapArgs.count("-?") || mapArgs.count("--help"))
- {
- // First part of help message is specific to bitcoind / RPC client
- std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
- _("Usage:") + "\n" +
- " bitcoind [options] " + "\n" +
- " bitcoind [options] <command> [params] " + _("Send command to -server or bitcoind") + "\n" +
- " bitcoind [options] help " + _("List commands") + "\n" +
- " bitcoind [options] help <command> " + _("Get help for a command") + "\n";
-
- strUsage += "\n" + HelpMessage();
-
- fprintf(stdout, "%s", strUsage.c_str());
- return false;
- }
-
- // Command-line RPC
- for (int i = 1; i < argc; i++)
- if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
- fCommandLine = true;
-
- if (fCommandLine)
- {
- int ret = CommandLineRPC(argc, argv);
- exit(ret);
- }
-#if !defined(WIN32)
- fDaemon = GetBoolArg("-daemon");
- if (fDaemon)
- {
- // Daemonize
- pid_t pid = fork();
- if (pid < 0)
- {
- fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno);
- return false;
- }
- if (pid > 0) // Parent process, pid is child process id
- {
- CreatePidFile(GetPidFile(), pid);
- return true;
- }
- // Child process falls through to rest of initialization
-
- pid_t sid = setsid();
- if (sid < 0)
- fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno);
- }
-#endif
-
- detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
- fRet = AppInit2(threadGroup);
- }
- catch (std::exception& e) {
- PrintExceptionContinue(&e, "AppInit()");
- } catch (...) {
- PrintExceptionContinue(NULL, "AppInit()");
- }
- if (!fRet) {
- if (detectShutdownThread)
- detectShutdownThread->interrupt();
- threadGroup.interrupt_all();
- }
-
- if (detectShutdownThread)
- {
- detectShutdownThread->join();
- delete detectShutdownThread;
- detectShutdownThread = NULL;
- }
- Shutdown();
-
- return fRet;
-}
-
-extern void noui_connect();
-int main(int argc, char* argv[])
-{
- bool fRet = false;
-
- // Connect bitcoind signal handlers
- noui_connect();
-
- fRet = AppInit(argc, argv);
-
- if (fRet && fDaemon)
- return 0;
-
- return (fRet ? 0 : 1);
-}
-#endif
-
bool static InitError(const std::string &str)
{
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
@@ -286,89 +163,90 @@ bool static Bind(const CService &addr, unsigned int flags) {
// Core-specific options shared between UI and daemon
std::string HelpMessage()
{
- string strUsage = _("Options:") + "\n" +
- " -? " + _("This help message") + "\n" +
- " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n" +
- " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n" +
- " -gen " + _("Generate coins (default: 0)") + "\n" +
- " -datadir=<dir> " + _("Specify data directory") + "\n" +
- " -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" +
- " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n" +
- " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" +
- " -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" +
- " -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"
- " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
- " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
- " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
- " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
- " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n" +
- " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
- " -externalip=<ip> " + _("Specify your own public address") + "\n" +
- " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n" +
- " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" +
- " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n" +
- " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" +
- " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n" +
- " -dnsseed " + _("Find peers using DNS lookup (default: 1 unless -connect)") + "\n" +
- " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
- " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
- " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n" +
- " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n" +
+ string strUsage = _("Options:") + "\n";
+ strUsage += " -? " + _("This help message") + "\n";
+ strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
+ strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
+ strUsage += " -gen " + _("Generate coins (default: 0)") + "\n";
+ strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
+ strUsage += " -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n";
+ strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
+ strUsage += " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n";
+ strUsage += " -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n";
+ strUsage += " -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n";
+ strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n";
+ strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
+ strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n";
+ strUsage += " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n";
+ strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n";
+ strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n";
+ strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n";
+ strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n";
+ strUsage += " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n";
+ strUsage += " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n";
+ strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n";
+ strUsage += " -bind=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n";
+ strUsage += " -dnsseed " + _("Find peers using DNS lookup (default: 1 unless -connect)") + "\n";
+ strUsage += " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n";
+ strUsage += " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n";
+ strUsage += " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n";
+ strUsage += " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n";
#ifdef USE_UPNP
#if USE_UPNP
- " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n" +
+ strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n";
#else
- " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n" +
+ strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n";
#endif
#endif
- " -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n" +
-#ifdef QT_GUI
- " -server " + _("Accept command line and JSON-RPC commands") + "\n" +
-#endif
-#if !defined(WIN32) && !defined(QT_GUI)
- " -daemon " + _("Run in the background as a daemon and accept commands") + "\n" +
+ strUsage += " -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n";
+ if (fHaveGUI)
+ strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n";
+#if !defined(WIN32)
+ if (fHaveGUI)
+ strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n";
#endif
- " -testnet " + _("Use the test network") + "\n" +
- " -debug " + _("Output extra debugging information. Implies all other -debug* options") + "\n" +
- " -debugnet " + _("Output extra network debugging information") + "\n" +
- " -logtimestamps " + _("Prepend debug output with timestamp") + "\n" +
- " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n" +
- " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n" +
+ strUsage += " -testnet " + _("Use the test network") + "\n";
+ strUsage += " -debug " + _("Output extra debugging information. Implies all other -debug* options") + "\n";
+ strUsage += " -debugnet " + _("Output extra network debugging information") + "\n";
+ strUsage += " -logtimestamps " + _("Prepend debug output with timestamp") + "\n";
+ strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n";
+ strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
+ strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
+ "solved instantly. This is intended for regression testing tools and app development.") + "\n";
#ifdef WIN32
- " -printtodebugger " + _("Send trace/debug info to debugger") + "\n" +
+ strUsage += " -printtodebugger " + _("Send trace/debug info to debugger") + "\n";
#endif
- " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n" +
- " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n" +
- " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n" +
- " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
-#ifndef QT_GUI
- " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
-#endif
- " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n" +
- " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
- " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n" +
- " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received (%s in cmd is replaced by message)") + "\n" +
- " -upgradewallet " + _("Upgrade wallet to latest format") + "\n" +
- " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n" +
- " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n" +
- " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n" +
- " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n" +
- " -checklevel=<n> " + _("How thorough the block verification is (0-4, default: 3)") + "\n" +
- " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n" +
- " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + "\n" +
- " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + "\n" +
- " -par=<n> " + _("Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)") + "\n" +
-
- "\n" + _("Block creation options:") + "\n" +
- " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n" +
- " -blockmaxsize=<n> " + _("Set maximum block size in bytes (default: 250000)") + "\n" +
- " -blockprioritysize=<n> " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n" +
-
- "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
- " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
- " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n" +
- " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n" +
- " -rpcsslciphers=<ciphers> " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
+ strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
+ strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
+ strUsage += " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n";
+ strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n";
+ if (!fHaveGUI)
+ strUsage += " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
+ strUsage += " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n";
+ strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n";
+ strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
+ strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received (%s in cmd is replaced by message)") + "\n";
+ strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + "\n";
+ strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
+ strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n";
+ strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n";
+ strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n";
+ strUsage += " -checklevel=<n> " + _("How thorough the block verification is (0-4, default: 3)") + "\n";
+ strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n";
+ strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + "\n";
+ strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + "\n";
+ strUsage += " -par=<n> " + _("Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)") + "\n";
+
+ strUsage += "\n"; _("Block creation options:") + "\n";
+ strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
+ strUsage += " -blockmaxsize=<n> " + _("Set maximum block size in bytes (default: 250000)") + "\n";
+ strUsage += " -blockprioritysize=<n> " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n";
+
+ strUsage += "\n"; _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
+ strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
+ strUsage += " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n";
+ strUsage += " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n";
+ strUsage += " -rpcsslciphers=<ciphers> " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
return strUsage;
}
@@ -491,7 +369,10 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 2: parameter interactions
- fTestNet = GetBoolArg("-testnet");
+ Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
+ if (!SelectParamsFromCommandLine()) {
+ return InitError("Invalid combination of -testnet and -regtest.");
+ }
if (mapArgs.count("-bind")) {
// when specifying an explicit binding address, you want to listen on it
@@ -521,7 +402,7 @@ bool AppInit2(boost::thread_group& threadGroup)
SoftSetBoolArg("-discover", false);
}
- if (GetBoolArg("-salvagewallet")) {
+ if (GetBoolArg("-salvagewallet", false)) {
// Rewrite just private keys: rescan to find transactions
SoftSetBoolArg("-rescan", true);
}
@@ -529,7 +410,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// Make sure enough file descriptors are available
int nBind = std::max((int)mapArgs.count("-bind"), 1);
nMaxConnections = GetArg("-maxconnections", 125);
- nMaxConnections = std::max(std::min(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS), 0);
+ nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
@@ -538,8 +419,8 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 3: parameter-to-internal-flags
- fDebug = GetBoolArg("-debug");
- fBenchmark = GetBoolArg("-benchmark");
+ fDebug = GetBoolArg("-debug", false);
+ fBenchmark = GetBoolArg("-benchmark", false);
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = GetArg("-par", 0);
@@ -554,20 +435,19 @@ bool AppInit2(boost::thread_group& threadGroup)
if (fDebug)
fDebugNet = true;
else
- fDebugNet = GetBoolArg("-debugnet");
+ fDebugNet = GetBoolArg("-debugnet", false);
if (fDaemon)
fServer = true;
else
- fServer = GetBoolArg("-server");
+ fServer = GetBoolArg("-server", false);
/* force fServer when running without GUI */
-#if !defined(QT_GUI)
- fServer = true;
-#endif
- fPrintToConsole = GetBoolArg("-printtoconsole");
- fPrintToDebugger = GetBoolArg("-printtodebugger");
- fLogTimestamps = GetBoolArg("-logtimestamps");
+ if (!fHaveGUI)
+ fServer = true;
+ fPrintToConsole = GetBoolArg("-printtoconsole", false);
+ fPrintToDebugger = GetBoolArg("-printtodebugger", false);
+ fLogTimestamps = GetBoolArg("-logtimestamps", false);
if (mapArgs.count("-timeout"))
{
@@ -672,7 +552,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
- if (GetBoolArg("-salvagewallet"))
+ if (GetBoolArg("-salvagewallet", false))
{
// Recover readable keypairs:
if (!CWalletDB::Recover(bitdb, "wallet.dat", true))
@@ -696,6 +576,8 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 6: network initialization
+ RegisterNodeSignals(GetNodeSignals());
+
int nSocksVersion = GetArg("-socks", 5);
if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
@@ -794,7 +676,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 7: load block chain
- fReindex = GetBoolArg("-reindex");
+ fReindex = GetBoolArg("-reindex", false);
// Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/
filesystem::path blocksDir = GetDataDir() / "blocks";
@@ -862,14 +744,26 @@ bool AppInit2(boost::thread_group& threadGroup)
break;
}
+ // If the loaded chain has a wrong genesis, bail out immediately
+ // (we're likely using a testnet datadir, or the other way around).
+ if (!mapBlockIndex.empty() && pindexGenesisBlock == NULL)
+ return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
+
// Initialize the block index (no-op if non-empty database was already loaded)
if (!InitBlockIndex()) {
strLoadError = _("Error initializing block database");
break;
}
+ // Check for changed -txindex state
+ if (fTxIndex != GetBoolArg("-txindex", false)) {
+ strLoadError = _("You need to rebuild the database using -reindex to change -txindex");
+ break;
+ }
+
uiInterface.InitMessage(_("Verifying blocks..."));
- if (!VerifyDB()) {
+ if (!VerifyDB(GetArg("-checklevel", 3),
+ GetArg( "-checkblocks", 288))) {
strLoadError = _("Corrupted block database detected");
break;
}
@@ -885,7 +779,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// first suggest a reindex
if (!fReset) {
bool fRet = uiInterface.ThreadSafeMessageBox(
- strLoadError + ".\n" + _("Do you want to rebuild the block database now?"),
+ strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?"),
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
if (fRet) {
fReindex = true;
@@ -899,9 +793,6 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
- if (mapArgs.count("-txindex") && fTxIndex != GetBoolArg("-txindex", false))
- return InitError(_("You need to rebuild the databases using -reindex to change -txindex"));
-
// as LoadBlockIndex can take several minutes, it's possible the user
// requested to kill bitcoin-qt during the last operation. If so, exit.
// As the program has not fully started yet, Shutdown() is possibly overkill.
@@ -912,7 +803,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
- if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
+ if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false))
{
PrintBlockTree();
return false;
@@ -929,7 +820,7 @@ bool AppInit2(boost::thread_group& threadGroup)
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
@@ -998,6 +889,8 @@ bool AppInit2(boost::thread_group& threadGroup)
if (!pwalletMain->SetAddressBookName(pwalletMain->vchDefaultKey.GetID(), ""))
strErrors << _("Cannot write default address") << "\n";
}
+
+ pwalletMain->SetBestChain(CBlockLocator(pindexBest));
}
printf("%s", strErrors.str().c_str());
@@ -1006,7 +899,7 @@ bool AppInit2(boost::thread_group& threadGroup)
RegisterWallet(pwalletMain);
CBlockIndex *pindexRescan = pindexBest;
- if (GetBoolArg("-rescan"))
+ if (GetBoolArg("-rescan", false))
pindexRescan = pindexGenesisBlock;
else
{
@@ -1077,6 +970,8 @@ bool AppInit2(boost::thread_group& threadGroup)
StartNode(threadGroup);
+ // InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly.
+ InitRPCMining();
if (fServer)
StartRPCThreads();
diff --git a/src/key.cpp b/src/key.cpp
index 20114e6bb2..f73708199a 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -2,13 +2,16 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <map>
-
#include <openssl/ecdsa.h>
+#include <openssl/rand.h>
#include <openssl/obj_mac.h>
#include "key.h"
+
+// anonymous namespace with local implementation code (OpenSSL interaction)
+namespace {
+
// Generate a private key from just the secret parameter
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
@@ -120,287 +123,273 @@ err:
return ret;
}
-void CKey::SetCompressedPubKey(bool fCompressed)
-{
- EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
- fCompressedPubKey = true;
-}
+// RAII Wrapper around OpenSSL's EC_KEY
+class CECKey {
+private:
+ EC_KEY *pkey;
-void CKey::Reset()
-{
- fCompressedPubKey = false;
- if (pkey != NULL)
+public:
+ CECKey() {
+ pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+ assert(pkey != NULL);
+ }
+
+ ~CECKey() {
EC_KEY_free(pkey);
- pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if (pkey == NULL)
- throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
- fSet = false;
-}
+ }
-CKey::CKey()
-{
- pkey = NULL;
- Reset();
-}
+ void GetSecretBytes(unsigned char vch[32]) const {
+ const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
+ assert(bn);
+ int nBytes = BN_num_bytes(bn);
+ int n=BN_bn2bin(bn,&vch[32 - nBytes]);
+ assert(n == nBytes);
+ memset(vch, 0, 32 - nBytes);
+ }
-CKey::CKey(const CKey& b)
-{
- pkey = EC_KEY_dup(b.pkey);
- if (pkey == NULL)
- throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
- fSet = b.fSet;
-}
+ void SetSecretBytes(const unsigned char vch[32]) {
+ BIGNUM bn;
+ BN_init(&bn);
+ assert(BN_bin2bn(vch, 32, &bn));
+ assert(EC_KEY_regenerate_key(pkey, &bn));
+ BN_clear_free(&bn);
+ }
-CKey& CKey::operator=(const CKey& b)
-{
- if (!EC_KEY_copy(pkey, b.pkey))
- throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
- fSet = b.fSet;
- return (*this);
-}
+ void GetPrivKey(CPrivKey &privkey) {
+ int nSize = i2d_ECPrivateKey(pkey, NULL);
+ assert(nSize);
+ privkey.resize(nSize);
+ unsigned char* pbegin = &privkey[0];
+ int nSize2 = i2d_ECPrivateKey(pkey, &pbegin);
+ assert(nSize == nSize2);
+ }
-CKey::~CKey()
-{
- EC_KEY_free(pkey);
-}
+ bool SetPrivKey(const CPrivKey &privkey) {
+ const unsigned char* pbegin = &privkey[0];
+ if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
+ // d2i_ECPrivateKey returns true if parsing succeeds.
+ // This doesn't necessarily mean the key is valid.
+ if (EC_KEY_check_key(pkey))
+ return true;
+ }
+ return false;
+ }
-bool CKey::IsNull() const
-{
- return !fSet;
-}
+ void GetPubKey(CPubKey &pubkey, bool fCompressed) {
+ EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
+ int nSize = i2o_ECPublicKey(pkey, NULL);
+ assert(nSize);
+ assert(nSize <= 65);
+ unsigned char c[65];
+ unsigned char *pbegin = c;
+ int nSize2 = i2o_ECPublicKey(pkey, &pbegin);
+ assert(nSize == nSize2);
+ pubkey.Set(&c[0], &c[nSize]);
+ }
-bool CKey::IsCompressed() const
-{
- return fCompressedPubKey;
-}
+ bool SetPubKey(const CPubKey &pubkey) {
+ const unsigned char* pbegin = pubkey.begin();
+ return o2i_ECPublicKey(&pkey, &pbegin, pubkey.size());
+ }
-void CKey::MakeNewKey(bool fCompressed)
-{
- if (!EC_KEY_generate_key(pkey))
- throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
- if (fCompressed)
- SetCompressedPubKey();
- fSet = true;
-}
+ bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) {
+ unsigned int nSize = ECDSA_size(pkey);
+ vchSig.resize(nSize); // Make sure it is big enough
+ assert(ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey));
+ vchSig.resize(nSize); // Shrink to fit actual size
+ return true;
+ }
-bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
-{
- const unsigned char* pbegin = &vchPrivKey[0];
- if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
- {
- // In testing, d2i_ECPrivateKey can return true
- // but fill in pkey with a key that fails
- // EC_KEY_check_key, so:
- if (EC_KEY_check_key(pkey))
- {
- fSet = true;
- return true;
+ bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
+ // -1 = error, 0 = bad sig, 1 = good
+ if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
+ return false;
+ return true;
+ }
+
+ bool SignCompact(const uint256 &hash, unsigned char *p64, int &rec) {
+ bool fOk = false;
+ ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
+ if (sig==NULL)
+ return false;
+ memset(p64, 0, 64);
+ int nBitsR = BN_num_bits(sig->r);
+ int nBitsS = BN_num_bits(sig->s);
+ if (nBitsR <= 256 && nBitsS <= 256) {
+ CPubKey pubkey;
+ GetPubKey(pubkey, true);
+ for (int i=0; i<4; i++) {
+ CECKey keyRec;
+ if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1) {
+ CPubKey pubkeyRec;
+ keyRec.GetPubKey(pubkeyRec, true);
+ if (pubkeyRec == pubkey) {
+ rec = i;
+ fOk = true;
+ break;
+ }
+ }
+ }
+ assert(fOk);
+ BN_bn2bin(sig->r,&p64[32-(nBitsR+7)/8]);
+ BN_bn2bin(sig->s,&p64[64-(nBitsS+7)/8]);
}
+ ECDSA_SIG_free(sig);
+ return fOk;
}
- // If vchPrivKey data is bad d2i_ECPrivateKey() can
- // leave pkey in a state where calling EC_KEY_free()
- // crashes. To avoid that, set pkey to NULL and
- // leak the memory (a leak is better than a crash)
- pkey = NULL;
- Reset();
- return false;
-}
-bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
-{
- EC_KEY_free(pkey);
- pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if (pkey == NULL)
- throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
- if (vchSecret.size() != 32)
- throw key_error("CKey::SetSecret() : secret must be 32 bytes");
- BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
- if (bn == NULL)
- throw key_error("CKey::SetSecret() : BN_bin2bn failed");
- if (!EC_KEY_regenerate_key(pkey,bn))
+ // reconstruct public key from a compact signature
+ // This is only slightly more CPU intensive than just verifying it.
+ // If this function succeeds, the recovered public key is guaranteed to be valid
+ // (the signature is a valid signature of the given data for that key)
+ bool Recover(const uint256 &hash, const unsigned char *p64, int rec)
{
- BN_clear_free(bn);
- throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
+ if (rec<0 || rec>=3)
+ return false;
+ ECDSA_SIG *sig = ECDSA_SIG_new();
+ BN_bin2bn(&p64[0], 32, sig->r);
+ BN_bin2bn(&p64[32], 32, sig->s);
+ bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1;
+ ECDSA_SIG_free(sig);
+ return ret;
+ }
+};
+
+}; // end of anonymous namespace
+
+bool CKey::Check(const unsigned char *vch) {
+ // Do not convert to OpenSSL's data structures for range-checking keys,
+ // it's easy enough to do directly.
+ static const unsigned char vchMax[32] = {
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+ 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
+ 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
+ };
+ bool fIsZero = true;
+ for (int i=0; i<32 && fIsZero; i++)
+ if (vch[i] != 0)
+ fIsZero = false;
+ if (fIsZero)
+ return false;
+ for (int i=0; i<32; i++) {
+ if (vch[i] < vchMax[i])
+ return true;
+ if (vch[i] > vchMax[i])
+ return false;
}
- BN_clear_free(bn);
- fSet = true;
- if (fCompressed || fCompressedPubKey)
- SetCompressedPubKey();
return true;
}
-CSecret CKey::GetSecret(bool &fCompressed) const
-{
- CSecret vchRet;
- vchRet.resize(32);
- const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
- int nBytes = BN_num_bytes(bn);
- if (bn == NULL)
- throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
- int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
- if (n != nBytes)
- throw key_error("CKey::GetSecret(): BN_bn2bin failed");
- fCompressed = fCompressedPubKey;
- return vchRet;
+void CKey::MakeNewKey(bool fCompressedIn) {
+ do {
+ RAND_bytes(vch, sizeof(vch));
+ } while (!Check(vch));
+ fValid = true;
+ fCompressed = fCompressedIn;
}
-CPrivKey CKey::GetPrivKey() const
-{
- int nSize = i2d_ECPrivateKey(pkey, NULL);
- if (!nSize)
- throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
- CPrivKey vchPrivKey(nSize, 0);
- unsigned char* pbegin = &vchPrivKey[0];
- if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
- throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
- return vchPrivKey;
+bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
+ CECKey key;
+ if (!key.SetPrivKey(privkey))
+ return false;
+ key.GetSecretBytes(vch);
+ fCompressed = fCompressedIn;
+ fValid = true;
+ return true;
}
-bool CKey::SetPubKey(const CPubKey& vchPubKey)
-{
- const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
- if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
- {
- fSet = true;
- if (vchPubKey.vchPubKey.size() == 33)
- SetCompressedPubKey();
- return true;
- }
- pkey = NULL;
- Reset();
- return false;
+CPrivKey CKey::GetPrivKey() const {
+ assert(fValid);
+ CECKey key;
+ key.SetSecretBytes(vch);
+ CPrivKey privkey;
+ key.GetPrivKey(privkey);
+ return privkey;
}
-CPubKey CKey::GetPubKey() const
-{
- int nSize = i2o_ECPublicKey(pkey, NULL);
- if (!nSize)
- throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
- std::vector<unsigned char> vchPubKey(nSize, 0);
- unsigned char* pbegin = &vchPubKey[0];
- if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
- throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
- return CPubKey(vchPubKey);
+CPubKey CKey::GetPubKey() const {
+ assert(fValid);
+ CECKey key;
+ key.SetSecretBytes(vch);
+ CPubKey pubkey;
+ key.GetPubKey(pubkey, fCompressed);
+ return pubkey;
}
-bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
-{
- unsigned int nSize = ECDSA_size(pkey);
- vchSig.resize(nSize); // Make sure it is big enough
- if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
- {
- vchSig.clear();
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
+ if (!fValid)
return false;
- }
- vchSig.resize(nSize); // Shrink to fit actual size
- return true;
+ CECKey key;
+ key.SetSecretBytes(vch);
+ return key.Sign(hash, vchSig);
}
-// create a compact signature (65 bytes), which allows reconstructing the used public key
-// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
-// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
-// 0x1D = second key with even y, 0x1E = second key with odd y
-bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
-{
- bool fOk = false;
- ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
- if (sig==NULL)
+bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
+ if (!fValid)
return false;
- vchSig.clear();
- vchSig.resize(65,0);
- int nBitsR = BN_num_bits(sig->r);
- int nBitsS = BN_num_bits(sig->s);
- if (nBitsR <= 256 && nBitsS <= 256)
- {
- int nRecId = -1;
- for (int i=0; i<4; i++)
- {
- CKey keyRec;
- keyRec.fSet = true;
- if (fCompressedPubKey)
- keyRec.SetCompressedPubKey();
- if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
- if (keyRec.GetPubKey() == this->GetPubKey())
- {
- nRecId = i;
- break;
- }
- }
-
- if (nRecId == -1)
- throw key_error("CKey::SignCompact() : unable to construct recoverable key");
+ CECKey key;
+ key.SetSecretBytes(vch);
+ vchSig.resize(65);
+ int rec = -1;
+ if (!key.SignCompact(hash, &vchSig[1], rec))
+ return false;
+ assert(rec != -1);
+ vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
+ return true;
+}
- vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
- BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
- BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
- fOk = true;
- }
- ECDSA_SIG_free(sig);
- return fOk;
+bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
+ if (!IsValid())
+ return false;
+ CECKey key;
+ if (!key.SetPubKey(*this))
+ return false;
+ if (!key.Verify(hash, vchSig))
+ return false;
+ return true;
}
-// reconstruct public key from a compact signature
-// This is only slightly more CPU intensive than just verifying it.
-// If this function succeeds, the recovered public key is guaranteed to be valid
-// (the signature is a valid signature of the given data for that key)
-bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
-{
+bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
if (vchSig.size() != 65)
return false;
- int nV = vchSig[0];
- if (nV<27 || nV>=35)
+ CECKey key;
+ if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
return false;
- ECDSA_SIG *sig = ECDSA_SIG_new();
- BN_bin2bn(&vchSig[1],32,sig->r);
- BN_bin2bn(&vchSig[33],32,sig->s);
-
- EC_KEY_free(pkey);
- pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if (nV >= 31)
- {
- SetCompressedPubKey();
- nV -= 4;
- }
- if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
- {
- fSet = true;
- ECDSA_SIG_free(sig);
- return true;
- }
- return false;
+ key.GetPubKey(*this, (vchSig[0] - 27) & 4);
+ return true;
}
-bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
-{
- // -1 = error, 0 = bad sig, 1 = good
- if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
+bool CPubKey::VerifyCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
+ if (!IsValid())
+ return false;
+ if (vchSig.size() != 65)
+ return false;
+ CECKey key;
+ if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4))
+ return false;
+ CPubKey pubkeyRec;
+ key.GetPubKey(pubkeyRec, IsCompressed());
+ if (*this != pubkeyRec)
return false;
-
return true;
}
-bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
-{
- CKey key;
- if (!key.SetCompactSignature(hash, vchSig))
+bool CPubKey::IsFullyValid() const {
+ if (!IsValid())
return false;
- if (GetPubKey() != key.GetPubKey())
+ CECKey key;
+ if (!key.SetPubKey(*this))
return false;
-
return true;
}
-bool CKey::IsValid()
-{
- if (!fSet)
+bool CPubKey::Decompress() {
+ if (!IsValid())
return false;
-
- if (!EC_KEY_check_key(pkey))
+ CECKey key;
+ if (!key.SetPubKey(*this))
return false;
-
- bool fCompr;
- CSecret secret = GetSecret(fCompr);
- CKey key2;
- key2.SetSecret(secret, fCompr);
- return GetPubKey() == key2.GetPubKey();
+ key.GetPubKey(*this, false);
+ return true;
}
diff --git a/src/key.h b/src/key.h
index 4da16b9cdb..ce469ad298 100644
--- a/src/key.h
+++ b/src/key.h
@@ -1,11 +1,10 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H
-#include <stdexcept>
#include <vector>
#include "allocators.h"
@@ -13,23 +12,6 @@
#include "uint256.h"
#include "hash.h"
-#include <openssl/ec.h> // for EC_KEY definition
-
-// secp160k1
-// const unsigned int PRIVATE_KEY_SIZE = 192;
-// const unsigned int PUBLIC_KEY_SIZE = 41;
-// const unsigned int SIGNATURE_SIZE = 48;
-//
-// secp192k1
-// const unsigned int PRIVATE_KEY_SIZE = 222;
-// const unsigned int PUBLIC_KEY_SIZE = 49;
-// const unsigned int SIGNATURE_SIZE = 57;
-//
-// secp224k1
-// const unsigned int PRIVATE_KEY_SIZE = 250;
-// const unsigned int PUBLIC_KEY_SIZE = 57;
-// const unsigned int SIGNATURE_SIZE = 66;
-//
// secp256k1:
// const unsigned int PRIVATE_KEY_SIZE = 279;
// const unsigned int PUBLIC_KEY_SIZE = 65;
@@ -38,12 +20,6 @@
// see www.keylength.com
// script supports up to 75 for single byte push
-class key_error : public std::runtime_error
-{
-public:
- explicit key_error(const std::string& str) : std::runtime_error(str) {}
-};
-
/** A reference to a CKey: the Hash160 of its serialized public key */
class CKeyID : public uint160
{
@@ -63,99 +39,218 @@ public:
/** An encapsulated public key. */
class CPubKey {
private:
- std::vector<unsigned char> vchPubKey;
- friend class CKey;
+ // Just store the serialized data.
+ // Its length can very cheaply be computed from the first byte.
+ unsigned char vch[65];
+
+ // Compute the length of a pubkey with a given first byte.
+ unsigned int static GetLen(unsigned char chHeader) {
+ if (chHeader == 2 || chHeader == 3)
+ return 33;
+ if (chHeader == 4 || chHeader == 6 || chHeader == 7)
+ return 65;
+ return 0;
+ }
+
+ // Set this key data to be invalid
+ void Invalidate() {
+ vch[0] = 0xFF;
+ }
public:
- CPubKey() { }
- CPubKey(const std::vector<unsigned char> &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { }
- friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; }
- friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; }
- friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; }
+ // Construct an invalid public key.
+ CPubKey() {
+ Invalidate();
+ }
- IMPLEMENT_SERIALIZE(
- READWRITE(vchPubKey);
- )
+ // Initialize a public key using begin/end iterators to byte data.
+ template<typename T>
+ void Set(const T pbegin, const T pend) {
+ int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
+ if (len && len == (pend-pbegin))
+ memcpy(vch, (unsigned char*)&pbegin[0], len);
+ else
+ Invalidate();
+ }
+
+ // Construct a public key using begin/end iterators to byte data.
+ template<typename T>
+ CPubKey(const T pbegin, const T pend) {
+ Set(pbegin, pend);
+ }
+
+ // Construct a public key from a byte vector.
+ CPubKey(const std::vector<unsigned char> &vch) {
+ Set(vch.begin(), vch.end());
+ }
+
+ // Simple read-only vector-like interface to the pubkey data.
+ unsigned int size() const { return GetLen(vch[0]); }
+ const unsigned char *begin() const { return vch; }
+ const unsigned char *end() const { return vch+size(); }
+ const unsigned char &operator[](unsigned int pos) const { return vch[pos]; }
+
+ // Comparator implementation.
+ friend bool operator==(const CPubKey &a, const CPubKey &b) {
+ return a.vch[0] == b.vch[0] &&
+ memcmp(a.vch, b.vch, a.size()) == 0;
+ }
+ friend bool operator!=(const CPubKey &a, const CPubKey &b) {
+ return !(a == b);
+ }
+ friend bool operator<(const CPubKey &a, const CPubKey &b) {
+ return a.vch[0] < b.vch[0] ||
+ (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
+ }
+
+ // Implement serialization, as if this was a byte vector.
+ unsigned int GetSerializeSize(int nType, int nVersion) const {
+ return size() + 1;
+ }
+ template<typename Stream> void Serialize(Stream &s, int nType, int nVersion) const {
+ unsigned int len = size();
+ ::WriteCompactSize(s, len);
+ s.write((char*)vch, len);
+ }
+ template<typename Stream> void Unserialize(Stream &s, int nType, int nVersion) {
+ unsigned int len = ::ReadCompactSize(s);
+ if (len <= 65) {
+ s.read((char*)vch, len);
+ } else {
+ // invalid pubkey, skip available data
+ char dummy;
+ while (len--)
+ s.read(&dummy, 1);
+ Invalidate();
+ }
+ }
+ // Get the KeyID of this public key (hash of its serialization)
CKeyID GetID() const {
- return CKeyID(Hash160(vchPubKey));
+ return CKeyID(Hash160(vch, vch+size()));
}
+ // Get the 256-bit hash of this public key.
uint256 GetHash() const {
- return Hash(vchPubKey.begin(), vchPubKey.end());
+ return Hash(vch, vch+size());
}
+ // just check syntactic correctness.
bool IsValid() const {
- return vchPubKey.size() == 33 || vchPubKey.size() == 65;
+ return size() > 0;
}
+ // fully validate whether this is a valid public key (more expensive than IsValid())
+ bool IsFullyValid() const;
+
+ // Check whether this is a compressed public key.
bool IsCompressed() const {
- return vchPubKey.size() == 33;
+ return size() == 33;
}
- std::vector<unsigned char> Raw() const {
- return vchPubKey;
- }
+ // Verify a DER signature (~72 bytes).
+ // If this public key is not fully valid, the return value will be false.
+ bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const;
+
+ // Verify a compact signature (~65 bytes).
+ // See CKey::SignCompact.
+ bool VerifyCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) const;
+
+ // Recover a public key from a compact signature.
+ bool RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig);
+
+ // Turn this public key into an uncompressed public key.
+ bool Decompress();
};
// secure_allocator is defined in allocators.h
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
-// CSecret is a serialization of just the secret parameter (32 bytes)
-typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
-/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
-class CKey
-{
-protected:
- EC_KEY* pkey;
- bool fSet;
- bool fCompressedPubKey;
+/** An encapsulated private key. */
+class CKey {
+private:
+ // Whether this private key is valid. We check for correctness when modifying the key
+ // data, so fValid should always correspond to the actual state.
+ bool fValid;
+ // Whether the public key corresponding to this private key is (to be) compressed.
+ bool fCompressed;
+
+ // The actual byte data
+ unsigned char vch[32];
+
+ // Check whether the 32-byte array pointed to be vch is valid keydata.
+ bool static Check(const unsigned char *vch);
public:
- void SetCompressedPubKey(bool fCompressed = true);
- void Reset();
+ // Construct an invalid private key.
+ CKey() : fValid(false) {
+ LockObject(vch);
+ }
+
+ // Copy constructor. This is necessary because of memlocking.
+ CKey(const CKey &secret) : fValid(secret.fValid), fCompressed(secret.fCompressed) {
+ LockObject(vch);
+ memcpy(vch, secret.vch, sizeof(vch));
+ }
+
+ // Destructor (again necessary because of memlocking).
+ ~CKey() {
+ UnlockObject(vch);
+ }
+
+ // Initialize using begin and end iterators to byte data.
+ template<typename T>
+ void Set(const T pbegin, const T pend, bool fCompressedIn) {
+ if (pend - pbegin != 32) {
+ fValid = false;
+ return;
+ }
+ if (Check(&pbegin[0])) {
+ memcpy(vch, (unsigned char*)&pbegin[0], 32);
+ fValid = true;
+ fCompressed = fCompressedIn;
+ } else {
+ fValid = false;
+ }
+ }
- CKey();
- CKey(const CKey& b);
+ // Simple read-only vector-like interface.
+ unsigned int size() const { return (fValid ? 32 : 0); }
+ const unsigned char *begin() const { return vch; }
+ const unsigned char *end() const { return vch + size(); }
- CKey& operator=(const CKey& b);
+ // Check whether this private key is valid.
+ bool IsValid() const { return fValid; }
- ~CKey();
+ // Check whether the public key corresponding to this private key is (to be) compressed.
+ bool IsCompressed() const { return fCompressed; }
- bool IsNull() const;
- bool IsCompressed() const;
+ // Initialize from a CPrivKey (serialized OpenSSL private key data).
+ bool SetPrivKey(const CPrivKey &vchPrivKey, bool fCompressed);
+ // Generate a new private key using a cryptographic PRNG.
void MakeNewKey(bool fCompressed);
- bool SetPrivKey(const CPrivKey& vchPrivKey);
- bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
- CSecret GetSecret(bool &fCompressed) const;
+
+ // Convert the private key to a CPrivKey (serialized OpenSSL private key data).
+ // This is expensive.
CPrivKey GetPrivKey() const;
- bool SetPubKey(const CPubKey& vchPubKey);
+
+ // Compute the public key from a private key.
+ // This is expensive.
CPubKey GetPubKey() const;
- bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
+ // Create a DER-serialized signature.
+ bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const;
- // create a compact signature (65 bytes), which allows reconstructing the used public key
+ // Create a compact signature (65 bytes), which allows reconstructing the used public key.
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
- // 0x1D = second key with even y, 0x1E = second key with odd y
- bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
-
- // reconstruct public key from a compact signature
- // This is only slightly more CPU intensive than just verifying it.
- // If this function succeeds, the recovered public key is guaranteed to be valid
- // (the signature is a valid signature of the given data for that key)
- bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
-
- bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
-
- // Verify a compact signature
- bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
-
- bool IsValid();
+ // 0x1D = second key with even y, 0x1E = second key with odd y,
+ // add 0x04 for compressed keys.
+ bool SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const;
};
#endif
diff --git a/src/keystore.cpp b/src/keystore.cpp
index e0cf805a19..808f8c24ef 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -15,61 +15,50 @@ bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
return true;
}
-bool CBasicKeyStore::AddKey(const CKey& key)
+bool CKeyStore::AddKey(const CKey &key) {
+ return AddKeyPubKey(key, key.GetPubKey());
+}
+
+bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
{
- bool fCompressed = false;
- CSecret secret = key.GetSecret(fCompressed);
- {
- LOCK(cs_KeyStore);
- mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed);
- }
+ LOCK(cs_KeyStore);
+ mapKeys[pubkey.GetID()] = key;
return true;
}
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
{
- {
- LOCK(cs_KeyStore);
- mapScripts[redeemScript.GetID()] = redeemScript;
- }
+ LOCK(cs_KeyStore);
+ mapScripts[redeemScript.GetID()] = redeemScript;
return true;
}
bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
{
- bool result;
- {
- LOCK(cs_KeyStore);
- result = (mapScripts.count(hash) > 0);
- }
- return result;
+ LOCK(cs_KeyStore);
+ return mapScripts.count(hash) > 0;
}
-
bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
{
+ LOCK(cs_KeyStore);
+ ScriptMap::const_iterator mi = mapScripts.find(hash);
+ if (mi != mapScripts.end())
{
- LOCK(cs_KeyStore);
- ScriptMap::const_iterator mi = mapScripts.find(hash);
- if (mi != mapScripts.end())
- {
- redeemScriptOut = (*mi).second;
- return true;
- }
+ redeemScriptOut = (*mi).second;
+ return true;
}
return false;
}
bool CCryptoKeyStore::SetCrypted()
{
- {
- LOCK(cs_KeyStore);
- if (fUseCrypto)
- return true;
- if (!mapKeys.empty())
- return false;
- fUseCrypto = true;
- }
+ LOCK(cs_KeyStore);
+ if (fUseCrypto)
+ return true;
+ if (!mapKeys.empty())
+ return false;
+ fUseCrypto = true;
return true;
}
@@ -99,14 +88,13 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CSecret vchSecret;
+ CKeyingMaterial vchSecret;
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
return false;
if (vchSecret.size() != 32)
return false;
CKey key;
- key.SetPubKey(vchPubKey);
- key.SetSecret(vchSecret);
+ key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
if (key.GetPubKey() == vchPubKey)
break;
return false;
@@ -117,23 +105,22 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
return true;
}
-bool CCryptoKeyStore::AddKey(const CKey& key)
+bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
{
{
LOCK(cs_KeyStore);
if (!IsCrypted())
- return CBasicKeyStore::AddKey(key);
+ return CBasicKeyStore::AddKeyPubKey(key, pubkey);
if (IsLocked())
return false;
std::vector<unsigned char> vchCryptedSecret;
- CPubKey vchPubKey = key.GetPubKey();
- bool fCompressed;
- if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
+ CKeyingMaterial vchSecret(key.begin(), key.end());
+ if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
return false;
- if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
+ if (!AddCryptedKey(pubkey, vchCryptedSecret))
return false;
}
return true;
@@ -164,13 +151,12 @@ bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
{
const CPubKey &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CSecret vchSecret;
+ CKeyingMaterial vchSecret;
if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
return false;
if (vchSecret.size() != 32)
return false;
- keyOut.SetPubKey(vchPubKey);
- keyOut.SetSecret(vchSecret);
+ keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
return true;
}
}
@@ -204,13 +190,11 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
fUseCrypto = true;
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
{
- CKey key;
- if (!key.SetSecret(mKey.second.first, mKey.second.second))
- return false;
- const CPubKey vchPubKey = key.GetPubKey();
+ const CKey &key = mKey.second;
+ CPubKey vchPubKey = key.GetPubKey();
+ CKeyingMaterial vchSecret(key.begin(), key.end());
std::vector<unsigned char> vchCryptedSecret;
- bool fCompressed;
- if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
+ if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
return false;
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
diff --git a/src/keystore.h b/src/keystore.h
index ab369bbf47..49a7bf569d 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -21,7 +21,8 @@ public:
virtual ~CKeyStore() {}
// Add a key to the store.
- virtual bool AddKey(const CKey& key) =0;
+ virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0;
+ virtual bool AddKey(const CKey &key);
// Check whether a key corresponding to a given address is present in the store.
virtual bool HaveKey(const CKeyID &address) const =0;
@@ -33,18 +34,9 @@ public:
virtual bool AddCScript(const CScript& redeemScript) =0;
virtual bool HaveCScript(const CScriptID &hash) const =0;
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
-
- virtual bool GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const
- {
- CKey key;
- if (!GetKey(address, key))
- return false;
- vchSecret = key.GetSecret(fCompressed);
- return true;
- }
};
-typedef std::map<CKeyID, std::pair<CSecret, bool> > KeyMap;
+typedef std::map<CKeyID, CKey> KeyMap;
typedef std::map<CScriptID, CScript > ScriptMap;
/** Basic key store, that keeps keys in an address->secret map */
@@ -55,7 +47,7 @@ protected:
ScriptMap mapScripts;
public:
- bool AddKey(const CKey& key);
+ bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
bool HaveKey(const CKeyID &address) const
{
bool result;
@@ -85,8 +77,7 @@ public:
KeyMap::const_iterator mi = mapKeys.find(address);
if (mi != mapKeys.end())
{
- keyOut.Reset();
- keyOut.SetSecret((*mi).second.first, (*mi).second.second);
+ keyOut = mi->second;
return true;
}
}
@@ -146,7 +137,7 @@ public:
bool Lock();
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
- bool AddKey(const CKey& key);
+ bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
bool HaveKey(const CKeyID &address) const
{
{
diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform
index 609cb51224..a3ad057eee 100755
--- a/src/leveldb/build_detect_platform
+++ b/src/leveldb/build_detect_platform
@@ -94,6 +94,12 @@ case "$TARGET_OS" in
PLATFORM_LIBS="-lpthread"
PORT_FILE=port/port_posix.cc
;;
+ GNU/kFreeBSD)
+ PLATFORM=OS_KFREEBSD
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD"
+ PLATFORM_LIBS="-lpthread"
+ PORT_FILE=port/port_posix.cc
+ ;;
NetBSD)
PLATFORM=OS_NETBSD
COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD"
diff --git a/src/main.cpp b/src/main.cpp
index e2bed52787..da928a4b90 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,6 +11,7 @@
#include "init.h"
#include "ui_interface.h"
#include "checkqueue.h"
+#include "chainparams.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -31,8 +32,7 @@ CTxMemPool mempool;
unsigned int nTransactionsUpdated = 0;
map<uint256, CBlockIndex*> mapBlockIndex;
-uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
-static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
+std::vector<CBlockIndex*> vBlockIndexByHeight;
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
uint256 nBestChainWork = 0;
@@ -47,6 +47,7 @@ bool fReindex = false;
bool fBenchmark = false;
bool fTxIndex = false;
unsigned int nCoinCacheSize = 5000;
+bool fHaveGUI = false;
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
int64 CTransaction::nMinTxFee = 10000; // Override with -mintxfee
@@ -156,11 +157,112 @@ void static ResendWalletTransactions()
pwallet->ResendWalletTransactions();
}
+//////////////////////////////////////////////////////////////////////////////
+//
+// Registration of network node signals.
+//
+
+void RegisterNodeSignals(CNodeSignals& nodeSignals)
+{
+ nodeSignals.ProcessMessages.connect(&ProcessMessages);
+ nodeSignals.SendMessages.connect(&SendMessages);
+}
+
+void UnregisterNodeSignals(CNodeSignals& nodeSignals)
+{
+ nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
+ nodeSignals.SendMessages.disconnect(&SendMessages);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CBlockLocator implementation
+//
+
+CBlockLocator::CBlockLocator(uint256 hashBlock)
+{
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi != mapBlockIndex.end())
+ Set((*mi).second);
+}
+void CBlockLocator::Set(const CBlockIndex* pindex)
+{
+ vHave.clear();
+ int nStep = 1;
+ while (pindex)
+ {
+ vHave.push_back(pindex->GetBlockHash());
+
+ // Exponentially larger steps back
+ for (int i = 0; pindex && i < nStep; i++)
+ pindex = pindex->pprev;
+ if (vHave.size() > 10)
+ nStep *= 2;
+ }
+ vHave.push_back(Params().HashGenesisBlock());
+}
+int CBlockLocator::GetDistanceBack()
+{
+ // Retrace how far back it was in the sender's branch
+ int nDistance = 0;
+ int nStep = 1;
+ BOOST_FOREACH(const uint256& hash, vHave)
+ {
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ if (mi != mapBlockIndex.end())
+ {
+ CBlockIndex* pindex = (*mi).second;
+ if (pindex->IsInMainChain())
+ return nDistance;
+ }
+ nDistance += nStep;
+ if (nDistance > 10)
+ nStep *= 2;
+ }
+ return nDistance;
+}
+CBlockIndex *CBlockLocator::GetBlockIndex()
+{
+ // Find the first block the caller has in the main chain
+ BOOST_FOREACH(const uint256& hash, vHave)
+ {
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ if (mi != mapBlockIndex.end())
+ {
+ CBlockIndex* pindex = (*mi).second;
+ if (pindex->IsInMainChain())
+ return pindex;
+ }
+ }
+ return pindexGenesisBlock;
+}
+uint256 CBlockLocator::GetBlockHash()
+{
+ // Find the first block the caller has in the main chain
+ BOOST_FOREACH(const uint256& hash, vHave)
+ {
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ if (mi != mapBlockIndex.end())
+ {
+ CBlockIndex* pindex = (*mi).second;
+ if (pindex->IsInMainChain())
+ return hash;
+ }
+ }
+ return Params().HashGenesisBlock();
+}
+int CBlockLocator::GetHeight()
+{
+ CBlockIndex* pindex = GetBlockIndex();
+ if (!pindex)
+ return 0;
+ return pindex->nHeight;
+}
//////////////////////////////////////////////////////////////////////////////
//
@@ -355,41 +457,23 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
-//////////////////////////////////////////////////////////////////////////////
-//
-// CTransaction / CTxOut
-//
-
-bool CTxOut::IsDust() const
+bool IsStandardTx(const CTransaction& tx)
{
- // "Dust" is defined in terms of CTransaction::nMinRelayTxFee,
- // which has units satoshis-per-kilobyte.
- // If you'd pay more than 1/3 in fees
- // to spend something, then we consider it dust.
- // A typical txout is 33 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend,
- // so dust is a txout less than 54 uBTC
- // (5430 satoshis) with default nMinRelayTxFee
- return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee);
-}
-
-bool CTransaction::IsStandard() const
-{
- if (nVersion > CTransaction::CURRENT_VERSION)
+ if (tx.nVersion > CTransaction::CURRENT_VERSION)
return false;
- if (!IsFinal())
+ if (!IsFinalTx(tx))
return false;
// Extremely large transactions with lots of inputs can cost the network
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
- unsigned int sz = this->GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
+ unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz >= MAX_STANDARD_TX_SIZE)
return false;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
@@ -399,15 +483,47 @@ bool CTransaction::IsStandard() const
if (!txin.scriptSig.IsPushOnly())
return false;
}
- BOOST_FOREACH(const CTxOut& txout, vout) {
+ BOOST_FOREACH(const CTxOut& txout, tx.vout) {
if (!::IsStandard(txout.scriptPubKey))
return false;
- if (txout.IsDust())
+ if (txout.IsDust(CTransaction::nMinRelayTxFee))
return false;
}
return true;
}
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
+{
+ // Time based nLockTime implemented in 0.1.6
+ if (tx.nLockTime == 0)
+ return true;
+ if (nBlockHeight == 0)
+ nBlockHeight = nBestHeight;
+ if (nBlockTime == 0)
+ nBlockTime = GetAdjustedTime();
+ if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
+ return true;
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ if (!txin.IsFinal())
+ return false;
+ return true;
+}
+
+/** Amount of bitcoins spent by the transaction.
+ @return sum of all outputs (note: does not include fees)
+ */
+int64 GetValueOut(const CTransaction& tx)
+{
+ int64 nValueOut = 0;
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ {
+ nValueOut += txout.nValue;
+ if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
+ throw std::runtime_error("GetValueOut() : value out of range");
+ }
+ return nValueOut;
+}
+
//
// Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts
@@ -419,14 +535,14 @@ bool CTransaction::IsStandard() const
// expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
//
-bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
+bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs)
{
- if (IsCoinBase())
+ if (tx.IsCoinBase())
return true; // Coinbases don't use vin normally
- for (unsigned int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
{
- const CTxOut& prev = GetOutputFor(vin[i], mapInputs);
+ const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
vector<vector<unsigned char> > vSolutions;
txnouttype whichType;
@@ -444,7 +560,7 @@ bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
// beside "push data" in the scriptSig the
// IsStandard() call returns false
vector<vector<unsigned char> > stack;
- if (!EvalScript(stack, vin[i].scriptSig, *this, i, false, 0))
+ if (!EvalScript(stack, tx.vin[i].scriptSig, tx, i, false, 0))
return false;
if (whichType == TX_SCRIPTHASH)
@@ -473,20 +589,34 @@ bool CTransaction::AreInputsStandard(CCoinsViewCache& mapInputs) const
return true;
}
-unsigned int CTransaction::GetLegacySigOpCount() const
+unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
return nSigOps;
}
+unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& inputs)
+{
+ if (tx.IsCoinBase())
+ return 0;
+
+ unsigned int nSigOps = 0;
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
+ if (prevout.scriptPubKey.IsPayToScriptHash())
+ nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
+ }
+ return nSigOps;
+}
int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
{
@@ -497,7 +627,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if (pcoinsTip->GetCoins(GetHash(), coins)) {
CBlockIndex *pindex = FindBlockByHeight(coins.nHeight);
if (pindex) {
- if (!blockTmp.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(blockTmp, pindex))
return 0;
pblock = &blockTmp;
}
@@ -541,25 +671,25 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
-bool CTransaction::CheckTransaction(CValidationState &state) const
+bool CheckTransaction(const CTransaction& tx, CValidationState &state)
{
// Basic checks that don't depend on any context
- if (vin.empty())
- return state.DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
- if (vout.empty())
- return state.DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
+ if (tx.vin.empty())
+ return state.DoS(10, error("CheckTransaction() : vin empty"));
+ if (tx.vout.empty())
+ return state.DoS(10, error("CheckTransaction() : vout empty"));
// Size limits
- if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
// Check for negative or overflow output values
int64 nValueOut = 0;
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (txout.nValue < 0)
- return state.DoS(100, error("CTransaction::CheckTransaction() : txout.nValue negative"));
+ return state.DoS(100, error("CheckTransaction() : txout.nValue negative"));
if (txout.nValue > MAX_MONEY)
- return state.DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
+ return state.DoS(100, error("CheckTransaction() : txout.nValue too high"));
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return state.DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
@@ -567,71 +697,55 @@ bool CTransaction::CheckTransaction(CValidationState &state) const
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
if (vInOutPoints.count(txin.prevout))
return state.DoS(100, error("CTransaction::CheckTransaction() : duplicate inputs"));
vInOutPoints.insert(txin.prevout);
}
- if (IsCoinBase())
+ if (tx.IsCoinBase())
{
- if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)
- return state.DoS(100, error("CTransaction::CheckTransaction() : coinbase script size"));
+ if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
+ return state.DoS(100, error("CheckTransaction() : coinbase script size"));
}
else
{
- BOOST_FOREACH(const CTxIn& txin, vin)
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (txin.prevout.IsNull())
- return state.DoS(10, error("CTransaction::CheckTransaction() : prevout is null"));
+ return state.DoS(10, error("CheckTransaction() : prevout is null"));
}
return true;
}
-int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree,
- enum GetMinFee_mode mode) const
+int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode)
{
// Base fee is either nMinTxFee or nMinRelayTxFee
- int64 nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee;
+ int64 nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee;
- unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
- unsigned int nNewBlockSize = nBlockSize + nBytes;
+ unsigned int nBytes = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
if (fAllowFree)
{
- if (nBlockSize == 1)
- {
- // Transactions under 10K are free
- // (about 4500 BTC if made of 50 BTC inputs)
- if (nBytes < 10000)
- nMinFee = 0;
- }
- else
- {
- // Free transaction area
- if (nNewBlockSize < 27000)
- nMinFee = 0;
- }
+ // There is a free transaction area in blocks created by most miners,
+ // * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
+ // to be considered to fall into this category
+ // * If we are creating a transaction we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 17000
+ // (= 10000) to be considered safe and assume they can likely make it into this section
+ if (nBytes < (mode == GMF_SEND ? (DEFAULT_BLOCK_PRIORITY_SIZE - 17000) : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
+ nMinFee = 0;
}
// To limit dust spam, require base fee if any output is less than 0.01
if (nMinFee < nBaseFee)
{
- BOOST_FOREACH(const CTxOut& txout, vout)
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
if (txout.nValue < CENT)
nMinFee = nBaseFee;
}
- // Raise the price as the block approaches full
- if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
- {
- if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
- return MAX_MONEY;
- nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
- }
-
if (!MoneyRange(nMinFee))
nMinFee = MAX_MONEY;
return nMinFee;
@@ -650,13 +764,13 @@ void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
}
}
-bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree,
+bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs)
{
if (pfMissingInputs)
*pfMissingInputs = false;
- if (!tx.CheckTransaction(state))
+ if (!CheckTransaction(tx, state))
return error("CTxMemPool::accept() : CheckTransaction failed");
// Coinbase is only valid in a block, not as a loose transaction
@@ -668,7 +782,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
- if (!fTestNet && !tx.IsStandard())
+ if (!TestNet() && !IsStandardTx(tx))
return error("CTxMemPool::accept() : nonstandard transaction type");
// is it already in the memory pool?
@@ -693,7 +807,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
if (i != 0)
return false;
ptxOld = mapNextTx[outpoint].ptx;
- if (ptxOld->IsFinal())
+ if (IsFinalTx(*ptxOld))
return false;
if (!tx.IsNewerThan(*ptxOld))
return false;
@@ -707,7 +821,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
}
}
- if (fCheckInputs)
{
CCoinsView dummy;
CCoinsViewCache view(dummy);
@@ -733,7 +846,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
}
// are the actual inputs available?
- if (!tx.HaveInputs(view))
+ if (!view.HaveInputs(tx))
return state.Invalid(error("CTxMemPool::accept() : inputs already spent"));
// Bring the best block into scope
@@ -744,18 +857,18 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
}
// Check for non-standard pay-to-script-hash in inputs
- if (!tx.AreInputsStandard(view) && !fTestNet)
+ if (!TestNet() && !AreInputsStandard(tx, view))
return error("CTxMemPool::accept() : nonstandard transaction input");
// Note: if you modify this code to accept non-standard transactions, then
// you should add code here to check that the transaction does a
// reasonable number of ECDSA signature verifications.
- int64 nFees = tx.GetValueIn(view)-tx.GetValueOut();
+ int64 nFees = view.GetValueIn(tx)-GetValueOut(tx);
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Don't accept it if it can't get into a block
- int64 txMinFee = tx.GetMinFee(1000, true, GMF_RELAY);
+ int64 txMinFee = GetMinFee(tx, true, GMF_RELAY);
if (fLimitFree && nFees < txMinFee)
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
hash.ToString().c_str(),
@@ -786,7 +899,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
- if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
+ if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().c_str());
}
@@ -815,14 +928,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return true;
}
-bool CTransaction::AcceptToMemoryPool(CValidationState &state, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs)
-{
- try {
- return mempool.accept(state, *this, fCheckInputs, fLimitFree, pfMissingInputs);
- } catch(std::runtime_error &e) {
- return state.Abort(_("System error: ") + e.what());
- }
-}
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
{
@@ -932,15 +1037,15 @@ int CMerkleTx::GetBlocksToMaturity() const
}
-bool CMerkleTx::AcceptToMemoryPool(bool fCheckInputs, bool fLimitFree)
+bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree)
{
CValidationState state;
- return CTransaction::AcceptToMemoryPool(state, fCheckInputs, fLimitFree);
+ return mempool.accept(state, *this, fLimitFree, NULL);
}
-bool CWalletTx::AcceptWalletTransaction(bool fCheckInputs)
+bool CWalletTx::AcceptWalletTransaction()
{
{
LOCK(mempool.cs);
@@ -951,10 +1056,10 @@ bool CWalletTx::AcceptWalletTransaction(bool fCheckInputs)
{
uint256 hash = tx.GetHash();
if (!mempool.exists(hash) && pcoinsTip->HaveCoins(hash))
- tx.AcceptToMemoryPool(fCheckInputs, false);
+ tx.AcceptToMemoryPool(false);
}
}
- return AcceptToMemoryPool(fCheckInputs, false);
+ return AcceptToMemoryPool(false);
}
return false;
}
@@ -1009,7 +1114,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
if (pindexSlow) {
CBlock block;
- if (block.ReadFromDisk(pindexSlow)) {
+ if (ReadBlockFromDisk(block, pindexSlow)) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
if (tx.GetHash() == hash) {
txOut = tx;
@@ -1036,27 +1141,67 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
static CBlockIndex* pblockindexFBBHLast;
CBlockIndex* FindBlockByHeight(int nHeight)
{
- CBlockIndex *pblockindex;
- if (nHeight < nBestHeight / 2)
- pblockindex = pindexGenesisBlock;
- else
- pblockindex = pindexBest;
- if (pblockindexFBBHLast && abs(nHeight - pblockindex->nHeight) > abs(nHeight - pblockindexFBBHLast->nHeight))
- pblockindex = pblockindexFBBHLast;
- while (pblockindex->nHeight > nHeight)
- pblockindex = pblockindex->pprev;
- while (pblockindex->nHeight < nHeight)
- pblockindex = pblockindex->pnext;
- pblockindexFBBHLast = pblockindex;
- return pblockindex;
+ if (nHeight >= (int)vBlockIndexByHeight.size())
+ return NULL;
+ return vBlockIndexByHeight[nHeight];
+}
+
+bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
+{
+ // Open history file to append
+ CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
+ if (!fileout)
+ return error("WriteBlockToDisk() : OpenBlockFile failed");
+
+ // Write index header
+ unsigned int nSize = fileout.GetSerializeSize(block);
+ fileout << FLATDATA(Params().MessageStart()) << nSize;
+
+ // Write block
+ long fileOutPos = ftell(fileout);
+ if (fileOutPos < 0)
+ return error("WriteBlockToDisk() : ftell failed");
+ pos.nPos = (unsigned int)fileOutPos;
+ fileout << block;
+
+ // Flush stdio buffers and commit to disk before returning
+ fflush(fileout);
+ if (!IsInitialBlockDownload())
+ FileCommit(fileout);
+
+ return true;
+}
+
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
+{
+ block.SetNull();
+
+ // Open history file to read
+ CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
+ if (!filein)
+ return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : OpenBlockFile failed");
+
+ // Read block
+ try {
+ filein >> block;
+ }
+ catch (std::exception &e) {
+ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ }
+
+ // Check the header
+ if (!CheckProofOfWork(block.GetHash(), block.nBits))
+ return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : errors in block header");
+
+ return true;
}
-bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
{
- if (!ReadFromDisk(pindex->GetBlockPos()))
+ if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
return false;
- if (GetHash() != pindex->GetBlockHash())
- return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
+ if (block.GetHash() != pindex->GetBlockHash())
+ return error("ReadBlockFromDisk(CBlock&, CBlockIndex*) : GetHash() doesn't match index");
return true;
}
@@ -1072,8 +1217,8 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
{
int64 nSubsidy = 50 * COIN;
- // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
- nSubsidy >>= (nHeight / 210000);
+ // Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
+ nSubsidy >>= (nHeight / Params().SubsidyHalvingInterval());
return nSubsidy + nFees;
}
@@ -1088,28 +1233,29 @@ static const int64 nInterval = nTargetTimespan / nTargetSpacing;
//
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
{
+ const CBigNum &bnLimit = Params().ProofOfWorkLimit();
// Testnet has min-difficulty blocks
// after nTargetSpacing*2 time between blocks:
- if (fTestNet && nTime > nTargetSpacing*2)
- return bnProofOfWorkLimit.GetCompact();
+ if (TestNet() && nTime > nTargetSpacing*2)
+ return bnLimit.GetCompact();
CBigNum bnResult;
bnResult.SetCompact(nBase);
- while (nTime > 0 && bnResult < bnProofOfWorkLimit)
+ while (nTime > 0 && bnResult < bnLimit)
{
// Maximum 400% adjustment...
bnResult *= 4;
// ... in best-case exactly 4-times-normal target time
nTime -= nTargetTimespan*4;
}
- if (bnResult > bnProofOfWorkLimit)
- bnResult = bnProofOfWorkLimit;
+ if (bnResult > bnLimit)
+ bnResult = bnLimit;
return bnResult.GetCompact();
}
unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
{
- unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
+ unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
// Genesis block
if (pindexLast == NULL)
@@ -1118,9 +1264,9 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
// Only change once per interval
if ((pindexLast->nHeight+1) % nInterval != 0)
{
- // Special difficulty rule for testnet:
- if (fTestNet)
+ if (TestNet())
{
+ // Special difficulty rule for testnet:
// If the new block's timestamp is more than 2* 10 minutes
// then allow mining of a min-difficulty block.
if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2)
@@ -1134,7 +1280,6 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
return pindex->nBits;
}
}
-
return pindexLast->nBits;
}
@@ -1158,8 +1303,8 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;
- if (bnNew > bnProofOfWorkLimit)
- bnNew = bnProofOfWorkLimit;
+ if (bnNew > Params().ProofOfWorkLimit())
+ bnNew = Params().ProofOfWorkLimit();
/// debug print
printf("GetNextWorkRequired RETARGET\n");
@@ -1176,7 +1321,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
bnTarget.SetCompact(nBits);
// Check range
- if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit)
+ if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
return error("CheckProofOfWork() : nBits below minimum work");
// Check proof of work matches claimed amount
@@ -1231,7 +1376,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
setBlockIndexValid.erase(pindex);
InvalidChainFound(pindex);
- if (pindex->pnext) {
+ if (pindex->GetNextInMainChain()) {
CValidationState stateDummy;
ConnectBestBlock(stateDummy); // reorganise away from the failed block
}
@@ -1271,7 +1416,7 @@ bool ConnectBestBlock(CValidationState &state) {
if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
vAttach.push_back(pindexTest);
- if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) {
+ if (pindexTest->pprev == NULL || pindexTest->GetNextInMainChain()) {
reverse(vAttach.begin(), vAttach.end());
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
boost::this_thread::interruption_point();
@@ -1289,13 +1434,13 @@ bool ConnectBestBlock(CValidationState &state) {
} while(true);
}
-void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
+void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
{
- nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
// Updating time can change work required on testnet:
- if (fTestNet)
- nBits = GetNextWorkRequired(pindexPrev, this);
+ if (TestNet())
+ block.nBits = GetNextWorkRequired(pindexPrev, &block);
}
@@ -1308,45 +1453,30 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
-const CTxOut &CTransaction::GetOutputFor(const CTxIn& input, CCoinsViewCache& view)
+const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input)
{
- const CCoins &coins = view.GetCoins(input.prevout.hash);
+ const CCoins &coins = GetCoins(input.prevout.hash);
assert(coins.IsAvailable(input.prevout.n));
return coins.vout[input.prevout.n];
}
-int64 CTransaction::GetValueIn(CCoinsViewCache& inputs) const
+int64 CCoinsViewCache::GetValueIn(const CTransaction& tx)
{
- if (IsCoinBase())
+ if (tx.IsCoinBase())
return 0;
int64 nResult = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
- nResult += GetOutputFor(vin[i], inputs).nValue;
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ nResult += GetOutputFor(tx.vin[i]).nValue;
return nResult;
}
-unsigned int CTransaction::GetP2SHSigOpCount(CCoinsViewCache& inputs) const
-{
- if (IsCoinBase())
- return 0;
-
- unsigned int nSigOps = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- const CTxOut &prevout = GetOutputFor(vin[i], inputs);
- if (prevout.scriptPubKey.IsPayToScriptHash())
- nSigOps += prevout.scriptPubKey.GetSigOpCount(vin[i].scriptSig);
- }
- return nSigOps;
-}
-
-bool CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) const
+void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash)
{
// mark inputs spent
- if (!IsCoinBase()) {
- BOOST_FOREACH(const CTxIn &txin, vin) {
+ if (!tx.IsCoinBase()) {
+ BOOST_FOREACH(const CTxIn &txin, tx.vin) {
CCoins &coins = inputs.GetCoins(txin.prevout.hash);
CTxInUndo undo;
assert(coins.Spend(txin.prevout, undo));
@@ -1355,25 +1485,23 @@ bool CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs,
}
// add outputs
- assert(inputs.SetCoins(txhash, CCoins(*this, nHeight)));
-
- return true;
+ assert(inputs.SetCoins(txhash, CCoins(tx, nHeight)));
}
-bool CTransaction::HaveInputs(CCoinsViewCache &inputs) const
+bool CCoinsViewCache::HaveInputs(const CTransaction& tx)
{
- if (!IsCoinBase()) {
+ if (!tx.IsCoinBase()) {
// first check whether information about the prevout hash is available
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
- if (!inputs.HaveCoins(prevout.hash))
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
+ if (!HaveCoins(prevout.hash))
return false;
}
// then check whether the actual outputs are available
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
- const CCoins &coins = inputs.GetCoins(prevout.hash);
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
+ const CCoins &coins = GetCoins(prevout.hash);
if (!coins.IsAvailable(prevout.n))
return false;
}
@@ -1393,26 +1521,26 @@ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned in
return CScriptCheck(txFrom, txTo, nIn, flags, nHashType)();
}
-bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks) const
+bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector<CScriptCheck> *pvChecks)
{
- if (!IsCoinBase())
+ if (!tx.IsCoinBase())
{
if (pvChecks)
- pvChecks->reserve(vin.size());
+ pvChecks->reserve(tx.vin.size());
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
// for an attacker to attempt to split the network.
- if (!HaveInputs(inputs))
- return state.Invalid(error("CheckInputs() : %s inputs unavailable", GetHash().ToString().c_str()));
+ if (!inputs.HaveInputs(tx))
+ return state.Invalid(error("CheckInputs() : %s inputs unavailable", tx.GetHash().ToString().c_str()));
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
int64 nValueIn = 0;
int64 nFees = 0;
- for (unsigned int i = 0; i < vin.size(); i++)
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
{
- const COutPoint &prevout = vin[i].prevout;
+ const COutPoint &prevout = tx.vin[i].prevout;
const CCoins &coins = inputs.GetCoins(prevout.hash);
// If prev is coinbase, check that it's matured
@@ -1428,13 +1556,13 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
}
- if (nValueIn < GetValueOut())
- return state.DoS(100, error("CheckInputs() : %s value in < value out", GetHash().ToString().c_str()));
+ if (nValueIn < GetValueOut(tx))
+ return state.DoS(100, error("CheckInputs() : %s value in < value out", tx.GetHash().ToString().c_str()));
// Tally transaction fees
- int64 nTxFee = nValueIn - GetValueOut();
+ int64 nTxFee = nValueIn - GetValueOut(tx);
if (nTxFee < 0)
- return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", GetHash().ToString().c_str()));
+ return state.DoS(100, error("CheckInputs() : %s nTxFee < 0", tx.GetHash().ToString().c_str()));
nFees += nTxFee;
if (!MoneyRange(nFees))
return state.DoS(100, error("CheckInputs() : nFees out of range"));
@@ -1447,12 +1575,12 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
// before the last block chain checkpoint. This is safe because block merkle hashes are
// still computed and checked, and any change will be caught at the next checkpoint.
if (fScriptChecks) {
- for (unsigned int i = 0; i < vin.size(); i++) {
- const COutPoint &prevout = vin[i].prevout;
+ for (unsigned int i = 0; i < tx.vin.size(); i++) {
+ const COutPoint &prevout = tx.vin[i].prevout;
const CCoins &coins = inputs.GetCoins(prevout.hash);
// Verify signature
- CScriptCheck check(coins, *this, i, flags, 0);
+ CScriptCheck check(coins, tx, i, flags, 0);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@@ -1460,7 +1588,7 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
if (flags & SCRIPT_VERIFY_STRICTENC) {
// For now, check whether the failure was caused by non-canonical
// encodings or not; if so, don't trigger DoS protection.
- CScriptCheck check(coins, *this, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0);
+ CScriptCheck check(coins, tx, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0);
if (check())
return state.Invalid();
}
@@ -1475,8 +1603,7 @@ bool CTransaction::CheckInputs(CValidationState &state, CCoinsViewCache &inputs,
-
-bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, bool *pfClean)
+bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{
assert(pindex == view.GetBestBlock());
@@ -1492,12 +1619,12 @@ bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoin
if (!blockUndo.ReadFromDisk(pos, pindex->pprev->GetBlockHash()))
return error("DisconnectBlock() : failure reading undo data");
- if (blockUndo.vtxundo.size() + 1 != vtx.size())
+ if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
return error("DisconnectBlock() : block and undo data inconsistent");
// undo transactions in reverse order
- for (int i = vtx.size() - 1; i >= 0; i--) {
- const CTransaction &tx = vtx[i];
+ for (int i = block.vtx.size() - 1; i >= 0; i--) {
+ const CTransaction &tx = block.vtx[i];
uint256 hash = tx.GetHash();
// check that all outputs are available
@@ -1590,10 +1717,10 @@ void ThreadScriptCheck() {
scriptcheckqueue.Thread();
}
-bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck)
+bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
{
// Check it again in case a previous version let a bad block in
- if (!CheckBlock(state, !fJustCheck, !fJustCheck))
+ if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
return false;
// verify that the view's current state corresponds to the previous block
@@ -1601,7 +1728,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
- if (GetHash() == hashGenesisBlock) {
+ if (block.GetHash() == Params().HashGenesisBlock()) {
view.SetBestBlock(pindex);
pindexGenesisBlock = pindex;
return true;
@@ -1625,8 +1752,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
- for (unsigned int i=0; i<vtx.size(); i++) {
- uint256 hash = GetTxHash(i);
+ for (unsigned int i = 0; i < block.vtx.size(); i++) {
+ uint256 hash = block.GetTxHash(i);
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
}
@@ -1647,21 +1774,21 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
int64 nFees = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
- CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(vtx.size()));
+ CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
- vPos.reserve(vtx.size());
- for (unsigned int i=0; i<vtx.size(); i++)
+ vPos.reserve(block.vtx.size());
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- const CTransaction &tx = vtx[i];
+ const CTransaction &tx = block.vtx[i];
nInputs += tx.vin.size();
- nSigOps += tx.GetLegacySigOpCount();
+ nSigOps += GetLegacySigOpCount(tx);
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"));
if (!tx.IsCoinBase())
{
- if (!tx.HaveInputs(view))
+ if (!view.HaveInputs(tx))
return state.DoS(100, error("ConnectBlock() : inputs missing/spent"));
if (fStrictPayToScriptHash)
@@ -1669,34 +1796,33 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
// Add in sigops done by pay-to-script-hash inputs;
// this is to prevent a "rogue miner" from creating
// an incredibly-expensive-to-validate block.
- nSigOps += tx.GetP2SHSigOpCount(view);
+ nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("ConnectBlock() : too many sigops"));
}
- nFees += tx.GetValueIn(view)-tx.GetValueOut();
+ nFees += view.GetValueIn(tx)-GetValueOut(tx);
std::vector<CScriptCheck> vChecks;
- if (!tx.CheckInputs(state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
+ if (!CheckInputs(tx, state, view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
return false;
control.Add(vChecks);
}
CTxUndo txundo;
- if (!tx.UpdateCoins(state, view, txundo, pindex->nHeight, GetTxHash(i)))
- return error("ConnectBlock() : UpdateInputs failed");
+ UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
- vPos.push_back(std::make_pair(GetTxHash(i), pos));
+ vPos.push_back(std::make_pair(block.GetTxHash(i), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
int64 nTime = GetTimeMicros() - nStart;
if (fBenchmark)
- printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)vtx.size(), 0.001 * nTime, 0.001 * nTime / vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
+ printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
- if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
- return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", vtx[0].GetValueOut(), GetBlockValue(pindex->nHeight, nFees)));
+ if (GetValueOut(block.vtx[0]) > GetBlockValue(pindex->nHeight, nFees))
+ return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(block.vtx[0]), GetBlockValue(pindex->nHeight, nFees)));
if (!control.Wait())
return state.DoS(100, false);
@@ -1737,8 +1863,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
assert(view.SetBestBlock(pindex));
// Watch for transactions paying to me
- for (unsigned int i=0; i<vtx.size(); i++)
- SyncWithWallets(GetTxHash(i), vtx[i], this, true);
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
+ SyncWithWallets(block.GetTxHash(i), block.vtx[i], &block, true);
return true;
}
@@ -1784,10 +1910,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
vector<CTransaction> vResurrect;
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
CBlock block;
- if (!block.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(block, pindex))
return state.Abort(_("Failed to read block"));
int64 nStart = GetTimeMicros();
- if (!block.DisconnectBlock(state, pindex, view))
+ if (!DisconnectBlock(block, state, pindex, view))
return error("SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str());
if (fBenchmark)
printf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
@@ -1804,10 +1930,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
vector<CTransaction> vDelete;
BOOST_FOREACH(CBlockIndex *pindex, vConnect) {
CBlock block;
- if (!block.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(block, pindex))
return state.Abort(_("Failed to read block"));
int64 nStart = GetTimeMicros();
- if (!block.ConnectBlock(state, pindex, view)) {
+ if (!ConnectBlock(block, state, pindex, view)) {
if (state.IsInvalid()) {
InvalidChainFound(pindexNew);
InvalidBlockFound(pindex);
@@ -1849,21 +1975,16 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// At this point, all changes have been done to the database.
// Proceed by updating the memory structures.
- // Disconnect shorter branch
- BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
- if (pindex->pprev)
- pindex->pprev->pnext = NULL;
-
- // Connect longer branch
+ // Register new best chain
+ vBlockIndexByHeight.resize(pindexNew->nHeight + 1);
BOOST_FOREACH(CBlockIndex* pindex, vConnect)
- if (pindex->pprev)
- pindex->pprev->pnext = pindex;
+ vBlockIndexByHeight[pindex->nHeight] = pindex;
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH(CTransaction& tx, vResurrect) {
// ignore validation errors in resurrected transactions
CValidationState stateDummy;
- tx.AcceptToMemoryPool(stateDummy, true, false);
+ mempool.accept(stateDummy, tx, false, NULL);
}
// Delete redundant memory transactions that are in the connected branch
@@ -1873,7 +1994,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
// Update best block in wallet (so we can detect restored wallets)
- if (!fIsInitialDownload)
+ if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
{
const CBlockLocator locator(pindexNew);
::SetBestChain(locator);
@@ -1922,25 +2043,25 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
-bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
+bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
// Check for duplicate
- uint256 hash = GetHash();
+ uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString().c_str()));
// Construct new block index object
- CBlockIndex* pindexNew = new CBlockIndex(*this);
+ CBlockIndex* pindexNew = new CBlockIndex(block);
assert(pindexNew);
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
- map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
+ map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
}
- pindexNew->nTx = vtx.size();
+ pindexNew->nTx = block.vtx.size();
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256();
pindexNew->nChainTx = (pindexNew->pprev ? pindexNew->pprev->nChainTx : 0) + pindexNew->nTx;
pindexNew->nFile = pos.nFile;
@@ -1961,7 +2082,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
// Notify UI to display prev block's coinbase if it was ours
static uint256 hashPrevBestCoinBase;
UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = GetTxHash(0);
+ hashPrevBestCoinBase = block.GetTxHash(0);
}
if (!pblocktree->Flush())
@@ -2067,111 +2188,92 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
}
-bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerkleRoot) const
+bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
// Size limits
- if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"));
- // Special short-term limits to avoid 10,000 BDB lock limit:
- if (GetBlockTime() >= 1363867200 && // start enforcing 21 March 2013, noon GMT
- GetBlockTime() < 1368576000) // stop enforcing 15 May 2013 00:00:00
- {
- // Rule is: #unique txids referenced <= 4,500
- // ... to prevent 10,000 BDB lock exhaustion on old clients
- set<uint256> setTxIn;
- for (size_t i = 0; i < vtx.size(); i++)
- {
- setTxIn.insert(vtx[i].GetHash());
- if (i == 0) continue; // skip coinbase txin
- BOOST_FOREACH(const CTxIn& txin, vtx[i].vin)
- setTxIn.insert(txin.prevout.hash);
- }
- size_t nTxids = setTxIn.size();
- if (nTxids > 4500)
- return error("CheckBlock() : 15 May maxlocks violation");
- }
-
// Check proof of work matches claimed amount
- if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
+ if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
return state.DoS(50, error("CheckBlock() : proof of work failed"));
// Check timestamp
- if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
+ if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"));
// First transaction must be coinbase, the rest must not be
- if (vtx.empty() || !vtx[0].IsCoinBase())
+ if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
return state.DoS(100, error("CheckBlock() : first tx is not coinbase"));
- for (unsigned int i = 1; i < vtx.size(); i++)
- if (vtx[i].IsCoinBase())
+ for (unsigned int i = 1; i < block.vtx.size(); i++)
+ if (block.vtx[i].IsCoinBase())
return state.DoS(100, error("CheckBlock() : more than one coinbase"));
// Check transactions
- BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!tx.CheckTransaction(state))
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
// Build the merkle tree already. We need it anyway later, and it makes the
// block cache the transaction hashes, which means they don't need to be
// recalculated many times during this block's validation.
- BuildMerkleTree();
+ block.BuildMerkleTree();
// Check for duplicate txids. This is caught by ConnectInputs(),
// but catching it earlier avoids a potential DoS attack:
set<uint256> uniqueTx;
- for (unsigned int i=0; i<vtx.size(); i++) {
- uniqueTx.insert(GetTxHash(i));
+ for (unsigned int i = 0; i < block.vtx.size(); i++) {
+ uniqueTx.insert(block.GetTxHash(i));
}
- if (uniqueTx.size() != vtx.size())
+ if (uniqueTx.size() != block.vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"));
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
{
- nSigOps += tx.GetLegacySigOpCount();
+ nSigOps += GetLegacySigOpCount(tx);
}
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
// Check merkle root
- if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree())
+ if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree())
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
return true;
}
-bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
+bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
{
// Check for duplicate
- uint256 hash = GetHash();
+ uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"));
// Get prev block index
CBlockIndex* pindexPrev = NULL;
int nHeight = 0;
- if (hash != hashGenesisBlock) {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
+ if (hash != Params().HashGenesisBlock()) {
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
return state.DoS(10, error("AcceptBlock() : prev block not found"));
pindexPrev = (*mi).second;
nHeight = pindexPrev->nHeight+1;
// Check proof of work
- if (nBits != GetNextWorkRequired(pindexPrev, this))
+ if (block.nBits != GetNextWorkRequired(pindexPrev, &block))
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"));
// Check timestamp against prev
- if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
+ if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"));
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!tx.IsFinal(nHeight, GetBlockTime()))
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ if (!IsFinalTx(tx, nHeight, block.GetBlockTime()))
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"));
// Check that the block chain matches the known block chain up to a checkpoint
@@ -2179,23 +2281,23 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
- if (nVersion < 2)
+ if (block.nVersion < 2)
{
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
+ if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
+ (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
{
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
}
}
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
- if (nVersion >= 2)
+ if (block.nVersion >= 2)
{
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
+ if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
+ (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
{
CScript expect = CScript() << nHeight;
- if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
+ if (!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin()))
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
}
}
@@ -2203,16 +2305,16 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
// Write block to history file
try {
- unsigned int nBlockSize = ::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION);
+ unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;
if (dbp != NULL)
blockPos = *dbp;
- if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, nTime, dbp != NULL))
+ if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.nTime, dbp != NULL))
return error("AcceptBlock() : FindBlockPos failed");
if (dbp == NULL)
- if (!WriteToDisk(blockPos))
+ if (!WriteBlockToDisk(block, blockPos))
return state.Abort(_("Failed to write block"));
- if (!AddToBlockIndex(state, blockPos))
+ if (!AddToBlockIndex(block, state, blockPos))
return error("AcceptBlock() : AddToBlockIndex failed");
} catch(std::runtime_error &e) {
return state.Abort(_("System error: ") + e.what());
@@ -2243,6 +2345,17 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
return (nFound >= nRequired);
}
+void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
+{
+ // Filter out duplicate requests
+ if (pindexBegin == pnode->pindexLastGetBlocksBegin && hashEnd == pnode->hashLastGetBlocksEnd)
+ return;
+ pnode->pindexLastGetBlocksBegin = pindexBegin;
+ pnode->hashLastGetBlocksEnd = hashEnd;
+
+ pnode->PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
+}
+
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
{
// Check for duplicate
@@ -2253,7 +2366,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString().c_str()));
// Preliminary checks
- if (!pblock->CheckBlock(state))
+ if (!CheckBlock(*pblock, state))
return error("ProcessBlock() : CheckBlock FAILED");
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
@@ -2288,13 +2401,13 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
// Ask this guy to fill in what we're missing
- pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2));
+ PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(pblock2));
}
return true;
}
// Store to disk
- if (!pblock->AcceptBlock(state, dbp))
+ if (!AcceptBlock(*pblock, state, dbp))
return error("ProcessBlock() : AcceptBlock FAILED");
// Recursively process any orphan blocks that depended on this one
@@ -2310,7 +2423,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
CBlock* pblockOrphan = (*mi).second;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned)
CValidationState stateDummy;
- if (pblockOrphan->AcceptBlock(stateDummy))
+ if (AcceptBlock(*pblockOrphan, stateDummy))
vWorkQueue.push_back(pblockOrphan->GetHash());
mapOrphanBlocks.erase(pblockOrphan->GetHash());
delete pblockOrphan;
@@ -2609,12 +2722,12 @@ bool static LoadBlockIndexDB()
nBestHeight = pindexBest->nHeight;
nBestChainWork = pindexBest->nChainWork;
- // set 'next' pointers in best chain
+ // register best chain
CBlockIndex *pindex = pindexBest;
- while(pindex != NULL && pindex->pprev != NULL) {
- CBlockIndex *pindexPrev = pindex->pprev;
- pindexPrev->pnext = pindex;
- pindex = pindexPrev;
+ vBlockIndexByHeight.resize(pindexBest->nHeight + 1);
+ while(pindex != NULL) {
+ vBlockIndexByHeight[pindex->nHeight] = pindex;
+ pindex = pindex->pprev;
}
printf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
hashBestChain.ToString().c_str(), nBestHeight,
@@ -2623,14 +2736,13 @@ bool static LoadBlockIndexDB()
return true;
}
-bool VerifyDB() {
+bool VerifyDB(int nCheckLevel, int nCheckDepth)
+{
if (pindexBest == NULL || pindexBest->pprev == NULL)
return true;
// Verify blocks in the best chain
- int nCheckLevel = GetArg("-checklevel", 3);
- int nCheckDepth = GetArg( "-checkblocks", 288);
- if (nCheckDepth == 0)
+ if (nCheckDepth <= 0)
nCheckDepth = 1000000000; // suffices until the year 19000
if (nCheckDepth > nBestHeight)
nCheckDepth = nBestHeight;
@@ -2648,10 +2760,10 @@ bool VerifyDB() {
break;
CBlock block;
// check level 0: read from disk
- if (!block.ReadFromDisk(pindex))
- return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ if (!ReadBlockFromDisk(block, pindex))
+ return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
// check level 1: verify block validity
- if (nCheckLevel >= 1 && !block.CheckBlock(state))
+ if (nCheckLevel >= 1 && !CheckBlock(block, state))
return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
@@ -2665,7 +2777,7 @@ bool VerifyDB() {
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= 2*nCoinCacheSize + 32000) {
bool fClean = true;
- if (!block.DisconnectBlock(state, pindex, coins, &fClean))
+ if (!DisconnectBlock(block, state, pindex, coins, &fClean))
return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
pindexState = pindex->pprev;
if (!fClean) {
@@ -2683,11 +2795,11 @@ bool VerifyDB() {
CBlockIndex *pindex = pindexState;
while (pindex != pindexBest) {
boost::this_thread::interruption_point();
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
CBlock block;
- if (!block.ReadFromDisk(pindex))
- return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
- if (!block.ConnectBlock(state, pindex, coins))
+ if (!ReadBlockFromDisk(block, pindex))
+ return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ if (!ConnectBlock(block, state, pindex, coins))
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
}
}
@@ -2711,21 +2823,9 @@ void UnloadBlockIndex()
bool LoadBlockIndex()
{
- if (fTestNet)
- {
- pchMessageStart[0] = 0x0b;
- pchMessageStart[1] = 0x11;
- pchMessageStart[2] = 0x09;
- pchMessageStart[3] = 0x07;
- hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
- }
-
- //
// Load block index from databases
- //
if (!fReindex && !LoadBlockIndexDB())
return false;
-
return true;
}
@@ -2742,55 +2842,17 @@ bool InitBlockIndex() {
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
if (!fReindex) {
- // Genesis Block:
- // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
- // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
- // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
- // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
- // vMerkleTree: 4a5e1e
-
- // Genesis block
- const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
- CTransaction txNew;
- txNew.vin.resize(1);
- txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
- txNew.vout[0].nValue = 50 * COIN;
- txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
- CBlock block;
- block.vtx.push_back(txNew);
- block.hashPrevBlock = 0;
- block.hashMerkleRoot = block.BuildMerkleTree();
- block.nVersion = 1;
- block.nTime = 1231006505;
- block.nBits = 0x1d00ffff;
- block.nNonce = 2083236893;
-
- if (fTestNet)
- {
- block.nTime = 1296688602;
- block.nNonce = 414098458;
- }
-
- //// debug print
- uint256 hash = block.GetHash();
- printf("%s\n", hash.ToString().c_str());
- printf("%s\n", hashGenesisBlock.ToString().c_str());
- printf("%s\n", block.hashMerkleRoot.ToString().c_str());
- assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- block.print();
- assert(hash == hashGenesisBlock);
-
- // Start new block file
try {
+ CBlock &block = const_cast<CBlock&>(Params().GenesisBlock());
+ // Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;
CValidationState state;
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.nTime))
return error("LoadBlockIndex() : FindBlockPos failed");
- if (!block.WriteToDisk(blockPos))
+ if (!WriteBlockToDisk(block, blockPos))
return error("LoadBlockIndex() : writing genesis block to disk failed");
- if (!block.AddToBlockIndex(state, blockPos))
+ if (!AddToBlockIndex(block, state, blockPos))
return error("LoadBlockIndex() : genesis block not accepted");
} catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
@@ -2846,7 +2908,7 @@ void PrintBlockTree()
// print item
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
printf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"",
pindex->nHeight,
pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos,
@@ -2859,7 +2921,7 @@ void PrintBlockTree()
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
{
- if (vNext[i]->pnext)
+ if (vNext[i]->GetNextInMainChain())
{
swap(vNext[0], vNext[i]);
break;
@@ -2899,10 +2961,10 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
try {
// locate a header
unsigned char buf[4];
- blkdat.FindByte(pchMessageStart[0]);
+ blkdat.FindByte(Params().MessageStart()[0]);
nRewind = blkdat.GetPos()+1;
blkdat >> FLATDATA(buf);
- if (memcmp(buf, pchMessageStart, 4))
+ if (memcmp(buf, Params().MessageStart(), 4))
continue;
// read size
blkdat >> nSize;
@@ -2967,7 +3029,7 @@ string GetWarnings(string strFor)
string strStatusBar;
string strRPC;
- if (GetBoolArg("-testsafemode"))
+ if (GetBoolArg("-testsafemode", false))
strRPC = "test";
if (!CLIENT_VERSION_IS_RELEASE)
@@ -3047,12 +3109,6 @@ bool static AlreadyHave(const CInv& inv)
-// The message start string is designed to be unlikely to occur in normal data.
-// The characters are rarely used upper ASCII, not valid as UTF-8, and produce
-// a large 4-byte int at any alignment.
-unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
-
-
void static ProcessGetData(CNode* pfrom)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
@@ -3076,7 +3132,7 @@ void static ProcessGetData(CNode* pfrom)
if (mi != mapBlockIndex.end())
{
CBlock block;
- block.ReadFromDisk((*mi).second);
+ ReadBlockFromDisk(block, (*mi).second);
if (inv.type == MSG_BLOCK)
pfrom->PushMessage("block", block);
else // MSG_FILTERED_BLOCK)
@@ -3392,12 +3448,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!fImporting && !fReindex)
pfrom->AskFor(inv);
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
- pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
+ PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
} else if (nInv == nLastBlock) {
// In case we are on a very long side-chain, it is possible that we already have
// the last block in an inv bundle sent in response to getblocks. Try to detect
// this situation and push another getblocks to continue.
- pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0));
+ PushGetBlocks(pfrom, mapBlockIndex[inv.hash], uint256(0));
if (fDebug)
printf("force request: %s\n", inv.ToString().c_str());
}
@@ -3440,10 +3496,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Send the rest of the chain
if (pindex)
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
int nLimit = 500;
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
- for (; pindex; pindex = pindex->pnext)
+ for (; pindex; pindex = pindex->GetNextInMainChain())
{
if (pindex->GetBlockHash() == hashStop)
{
@@ -3483,14 +3539,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Find the last block the caller has in the main chain
pindex = locator.GetBlockIndex();
if (pindex)
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
}
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders;
int nLimit = 2000;
printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
- for (; pindex; pindex = pindex->pnext)
+ for (; pindex; pindex = pindex->GetNextInMainChain())
{
vHeaders.push_back(pindex->GetBlockHeader());
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
@@ -3513,7 +3569,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool fMissingInputs = false;
CValidationState state;
- if (tx.AcceptToMemoryPool(state, true, true, &fMissingInputs))
+ if (mempool.accept(state, tx, true, &fMissingInputs))
{
RelayTransaction(tx, inv.hash, vMsg);
mapAlreadyAskedFor.erase(inv);
@@ -3536,7 +3592,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get anyone relaying LegitTxX banned)
CValidationState stateDummy;
- if (tx.AcceptToMemoryPool(stateDummy, true, true, &fMissingInputs2))
+ if (mempool.accept(stateDummy, tx, true, &fMissingInputs2))
{
printf(" accepted orphan tx %s\n", inv.hash.ToString().c_str());
RelayTransaction(tx, inv.hash, vMsg);
@@ -3775,7 +3831,7 @@ bool ProcessMessages(CNode* pfrom)
it++;
// Scan for message start
- if (memcmp(msg.hdr.pchMessageStart, pchMessageStart, sizeof(pchMessageStart)) != 0) {
+ if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
printf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n");
fOk = false;
break;
@@ -3874,7 +3930,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// Start block sync
if (pto->fStartSync && !fImporting && !fReindex) {
pto->fStartSync = false;
- pto->PushGetBlocks(pindexBest, uint256(0));
+ PushGetBlocks(pto, pindexBest, uint256(0));
}
// Resend wallet transactions that haven't gotten in a block yet
@@ -4191,13 +4247,9 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
- // Special compatibility rule before 15 May: limit size to 500,000 bytes:
- if (GetAdjustedTime() < 1368576000)
- nBlockMaxSize = std::min(nBlockMaxSize, (unsigned int)(MAX_BLOCK_SIZE_GEN));
-
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
- unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
+ unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
// Minimum block size you want to create; block will be filled with free transactions
@@ -4215,7 +4267,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Priority order to process transactions
list<COrphan> vOrphan; // list memory doesn't move
map<uint256, vector<COrphan*> > mapDependers;
- bool fPrintPriority = GetBoolArg("-printpriority");
+ bool fPrintPriority = GetBoolArg("-printpriority", false);
// This vector will be sorted into a priority queue:
vector<TxPriority> vecPriority;
@@ -4223,7 +4275,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
{
CTransaction& tx = (*mi).second;
- if (tx.IsCoinBase() || !tx.IsFinal())
+ if (tx.IsCoinBase() || !IsFinalTx(tx))
continue;
COrphan* porphan = NULL;
@@ -4233,8 +4285,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Read prev transaction
- CCoins coins;
- if (!view.GetCoins(txin.prevout.hash, coins))
+ if (!view.HaveCoins(txin.prevout.hash))
{
// This should never happen; all transactions in the memory
// pool should connect to either transactions in the chain
@@ -4261,6 +4312,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue;
continue;
}
+ const CCoins &coins = view.GetCoins(txin.prevout.hash);
int64 nValueIn = coins.vout[txin.prevout.n].nValue;
nTotalIn += nValueIn;
@@ -4278,7 +4330,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// This is a more accurate fee-per-kilobyte than is used by the client code, because the
// client code rounds up the size to the nearest 1K. That's good, because it gives an
// incentive to create smaller transactions.
- double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
+ double dFeePerKb = double(nTotalIn-GetValueOut(tx)) / (double(nTxSize)/1000.0);
if (porphan)
{
@@ -4308,16 +4360,13 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
vecPriority.pop_back();
- // second layer cached modifications just for this transaction
- CCoinsViewCache viewTemp(view, true);
-
// Size limits
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
if (nBlockSize + nTxSize >= nBlockMaxSize)
continue;
// Legacy limits on sigOps:
- unsigned int nTxSigOps = tx.GetLegacySigOpCount();
+ unsigned int nTxSigOps = GetLegacySigOpCount(tx);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
@@ -4328,33 +4377,29 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Prioritize by fee once past the priority size or we run out of high-priority
// transactions:
if (!fSortedByFee &&
- ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250)))
+ ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
{
fSortedByFee = true;
comparer = TxPriorityCompare(fSortedByFee);
std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
}
- if (!tx.HaveInputs(viewTemp))
+ if (!view.HaveInputs(tx))
continue;
- int64 nTxFees = tx.GetValueIn(viewTemp)-tx.GetValueOut();
+ int64 nTxFees = view.GetValueIn(tx)-GetValueOut(tx);
- nTxSigOps += tx.GetP2SHSigOpCount(viewTemp);
+ nTxSigOps += GetP2SHSigOpCount(tx, view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
CValidationState state;
- if (!tx.CheckInputs(state, viewTemp, true, SCRIPT_VERIFY_P2SH))
+ if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH))
continue;
CTxUndo txundo;
uint256 hash = tx.GetHash();
- if (!tx.UpdateCoins(state, viewTemp, txundo, pindexPrev->nHeight+1, hash))
- continue;
-
- // push changes from the second layer cache to the first one
- viewTemp.Flush();
+ UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
// Added
pblock->vtx.push_back(tx);
@@ -4398,18 +4443,18 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
- pblock->UpdateTime(pindexPrev);
+ UpdateTime(*pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
- pblocktemplate->vTxSigOps[0] = pblock->vtx[0].GetLegacySigOpCount();
+ pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1;
CCoinsViewCache viewNew(*pcoinsTip, true);
CValidationState state;
- if (!pblock->ConnectBlock(state, &indexDummy, viewNew, true))
+ if (!ConnectBlock(*pblock, state, &indexDummy, viewNew, true))
throw std::runtime_error("CreateNewBlock() : ConnectBlock failed");
}
@@ -4530,8 +4575,12 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nExtraNonce = 0;
try { loop {
- while (vNodes.empty())
- MilliSleep(1000);
+ if (Params().NetworkID() != CChainParams::REGTEST) {
+ // Busy-wait for the network to come online so we don't waste time mining
+ // on an obsolete chain. In regtest mode we expect to fly solo.
+ while (vNodes.empty())
+ MilliSleep(1000);
+ }
//
// Create new block
@@ -4593,6 +4642,12 @@ void static BitcoinMiner(CWallet *pwallet)
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckWork(pblock, *pwalletMain, reservekey);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
+
+ // In regression test mode, stop mining after a block is found. This
+ // allows developers to controllably generate a block on demand.
+ if (Params().NetworkID() == CChainParams::REGTEST)
+ throw boost::thread_interrupted();
+
break;
}
}
@@ -4628,7 +4683,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
- if (vNodes.empty())
+ if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST)
break;
if (nBlockNonce >= 0xffff0000)
break;
@@ -4638,9 +4693,9 @@ void static BitcoinMiner(CWallet *pwallet)
break;
// Update nTime every few seconds
- pblock->UpdateTime(pindexPrev);
+ UpdateTime(*pblock, pindexPrev);
nBlockTime = ByteReverse(pblock->nTime);
- if (fTestNet)
+ if (TestNet())
{
// Changing pblock->nTime can change work required on testnet:
nBlockBits = ByteReverse(pblock->nBits);
@@ -4660,8 +4715,12 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
static boost::thread_group* minerThreads = NULL;
int nThreads = GetArg("-genproclimit", -1);
- if (nThreads < 0)
- nThreads = boost::thread::hardware_concurrency();
+ if (nThreads < 0) {
+ if (Params().NetworkID() == CChainParams::REGTEST)
+ nThreads = 1;
+ else
+ nThreads = boost::thread::hardware_concurrency();
+ }
if (minerThreads != NULL)
{
diff --git a/src/main.h b/src/main.h
index cba8421c85..9e0235fa57 100644
--- a/src/main.h
+++ b/src/main.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
+#include "core.h"
#include "bignum.h"
#include "sync.h"
#include "net.h"
@@ -34,8 +35,6 @@ static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5;
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
-/** The maximum number of entries in an 'inv' protocol message */
-static const unsigned int MAX_INV_SZ = 50000;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
@@ -53,6 +52,8 @@ static const int COINBASE_MATURITY = 100;
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
+/** Default amount of block size reserved for high-priority transactions (in bytes) */
+static const int DEFAULT_BLOCK_PRIORITY_SIZE = 27000;
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
@@ -69,8 +70,8 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
+extern std::vector<CBlockIndex*> vBlockIndexByHeight;
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
-extern uint256 hashGenesisBlock;
extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern uint256 nBestChainWork;
@@ -86,13 +87,13 @@ extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
-extern unsigned char pchMessageStart[4];
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
extern int nScriptCheckThreads;
extern bool fTxIndex;
extern unsigned int nCoinCacheSize;
+extern bool fHaveGUI;
// Settings
extern int64 nTransactionFee;
@@ -120,6 +121,14 @@ void RegisterWallet(CWallet* pwalletIn);
void UnregisterWallet(CWallet* pwalletIn);
/** Push an updated transaction to all registered wallets */
void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
+
+/** Register with a network node to receive its signals */
+void RegisterNodeSignals(CNodeSignals& nodeSignals);
+/** Unregister a network node */
+void UnregisterNodeSignals(CNodeSignals& nodeSignals);
+
+void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd);
+
/** Process an incoming block */
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */
@@ -137,7 +146,7 @@ bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
/** Verify consistency of the block and coin databases */
-bool VerifyDB();
+bool VerifyDB(int nCheckLevel, int nCheckDepth);
/** Print the loaded block tree */
void PrintBlockTree();
/** Find a block by height in the currently-connected chain */
@@ -174,6 +183,9 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b
bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew);
/** Find the best known block, and make it the tip of the block chain */
bool ConnectBestBlock(CValidationState &state);
+
+void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev);
+
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
/** Verify a signature */
@@ -247,510 +259,79 @@ struct CDiskTxPos : public CDiskBlockPos
};
-/** An inpoint - a combination of a transaction and an index n into its vin */
-class CInPoint
-{
-public:
- CTransaction* ptx;
- unsigned int n;
-
- CInPoint() { SetNull(); }
- CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
- void SetNull() { ptx = NULL; n = (unsigned int) -1; }
- bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
-};
-
-
-
-/** An outpoint - a combination of a transaction hash and an index n into its vout */
-class COutPoint
-{
-public:
- uint256 hash;
- unsigned int n;
-
- COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
- IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
- void SetNull() { hash = 0; n = (unsigned int) -1; }
- bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
-
- friend bool operator<(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
- }
-
- friend bool operator==(const COutPoint& a, const COutPoint& b)
- {
- return (a.hash == b.hash && a.n == b.n);
- }
-
- friend bool operator!=(const COutPoint& a, const COutPoint& b)
- {
- return !(a == b);
- }
-
- std::string ToString() const
- {
- return strprintf("COutPoint(%s, %u)", hash.ToString().c_str(), n);
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
-};
-
-
-
-
-/** An input of a transaction. It contains the location of the previous
- * transaction's output that it claims and a signature that matches the
- * output's public key.
- */
-class CTxIn
-{
-public:
- COutPoint prevout;
- CScript scriptSig;
- unsigned int nSequence;
-
- CTxIn()
- {
- nSequence = std::numeric_limits<unsigned int>::max();
- }
-
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
- {
- prevout = prevoutIn;
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
-
- CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
- {
- prevout = COutPoint(hashPrevTx, nOut);
- scriptSig = scriptSigIn;
- nSequence = nSequenceIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- )
-
- bool IsFinal() const
- {
- return (nSequence == std::numeric_limits<unsigned int>::max());
- }
-
- friend bool operator==(const CTxIn& a, const CTxIn& b)
- {
- return (a.prevout == b.prevout &&
- a.scriptSig == b.scriptSig &&
- a.nSequence == b.nSequence);
- }
-
- friend bool operator!=(const CTxIn& a, const CTxIn& b)
- {
- return !(a == b);
- }
-
- std::string ToString() const
- {
- std::string str;
- str += "CTxIn(";
- str += prevout.ToString();
- if (prevout.IsNull())
- str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
- else
- str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
- if (nSequence != std::numeric_limits<unsigned int>::max())
- str += strprintf(", nSequence=%u", nSequence);
- str += ")";
- return str;
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
-};
-
-
-
-
-/** An output of a transaction. It contains the public key that the next input
- * must be able to sign with to claim it.
- */
-class CTxOut
-{
-public:
- int64 nValue;
- CScript scriptPubKey;
-
- CTxOut()
- {
- SetNull();
- }
-
- CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
- {
- nValue = nValueIn;
- scriptPubKey = scriptPubKeyIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- )
-
- void SetNull()
- {
- nValue = -1;
- scriptPubKey.clear();
- }
-
- bool IsNull() const
- {
- return (nValue == -1);
- }
-
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
-
- friend bool operator==(const CTxOut& a, const CTxOut& b)
- {
- return (a.nValue == b.nValue &&
- a.scriptPubKey == b.scriptPubKey);
- }
-
- friend bool operator!=(const CTxOut& a, const CTxOut& b)
- {
- return !(a == b);
- }
-
- bool IsDust() const;
-
- std::string ToString() const
- {
- if (scriptPubKey.size() < 6)
- return "CTxOut(error)";
- return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
- }
-
- void print() const
- {
- printf("%s\n", ToString().c_str());
- }
-};
-
-
enum GetMinFee_mode
{
- GMF_BLOCK,
GMF_RELAY,
GMF_SEND,
};
-/** The basic transaction that is broadcasted on the network and contained in
- * blocks. A transaction can contain multiple inputs and outputs.
- */
-class CTransaction
-{
-public:
- static int64 nMinTxFee;
- static int64 nMinRelayTxFee;
- static const int CURRENT_VERSION=1;
- int nVersion;
- std::vector<CTxIn> vin;
- std::vector<CTxOut> vout;
- unsigned int nLockTime;
-
- CTransaction()
- {
- SetNull();
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(vin);
- READWRITE(vout);
- READWRITE(nLockTime);
- )
-
- void SetNull()
- {
- nVersion = CTransaction::CURRENT_VERSION;
- vin.clear();
- vout.clear();
- nLockTime = 0;
- }
-
- bool IsNull() const
- {
- return (vin.empty() && vout.empty());
- }
-
- uint256 GetHash() const
- {
- return SerializeHash(*this);
- }
+int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode);
- bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
- {
- // Time based nLockTime implemented in 0.1.6
- if (nLockTime == 0)
- return true;
- if (nBlockHeight == 0)
- nBlockHeight = nBestHeight;
- if (nBlockTime == 0)
- nBlockTime = GetAdjustedTime();
- if ((int64)nLockTime < ((int64)nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
- return true;
- BOOST_FOREACH(const CTxIn& txin, vin)
- if (!txin.IsFinal())
- return false;
- return true;
- }
-
- bool IsNewerThan(const CTransaction& old) const
- {
- if (vin.size() != old.vin.size())
- return false;
- for (unsigned int i = 0; i < vin.size(); i++)
- if (vin[i].prevout != old.vin[i].prevout)
- return false;
-
- bool fNewer = false;
- unsigned int nLowest = std::numeric_limits<unsigned int>::max();
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != old.vin[i].nSequence)
- {
- if (vin[i].nSequence <= nLowest)
- {
- fNewer = false;
- nLowest = vin[i].nSequence;
- }
- if (old.vin[i].nSequence < nLowest)
- {
- fNewer = true;
- nLowest = old.vin[i].nSequence;
- }
- }
- }
- return fNewer;
- }
-
- bool IsCoinBase() const
- {
- return (vin.size() == 1 && vin[0].prevout.IsNull());
- }
+//
+// Check transaction inputs, and make sure any
+// pay-to-script-hash transactions are evaluating IsStandard scripts
+//
+// Why bother? To avoid denial-of-service attacks; an attacker
+// can submit a standard HASH... OP_EQUAL transaction,
+// which will get accepted into blocks. The redemption
+// script can be anything; an attacker could use a very
+// expensive-to-check-upon-redemption script like:
+// DUP CHECKSIG DROP ... repeated 100 times... OP_1
+//
/** Check for standard transaction types
- @return True if all outputs (scriptPubKeys) use only standard transaction forms
- */
- bool IsStandard() const;
-
- /** Check for standard transaction types
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ @param[in] mapInputs Map of previous transactions that have outputs we're spending
@return True if all inputs (scriptSigs) use only standard transaction forms
*/
- bool AreInputsStandard(CCoinsViewCache& mapInputs) const;
-
- /** Count ECDSA signature operations the old-fashioned (pre-0.6) way
- @return number of sigops this transaction's outputs will produce when spent
- */
- unsigned int GetLegacySigOpCount() const;
+bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs);
- /** Count ECDSA signature operations in pay-to-script-hash inputs.
+/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
+ @return number of sigops this transaction's outputs will produce when spent
+ @see CTransaction::FetchInputs
+*/
+unsigned int GetLegacySigOpCount(const CTransaction& tx);
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return maximum number of sigops required to validate this transaction's inputs
- */
- unsigned int GetP2SHSigOpCount(CCoinsViewCache& mapInputs) const;
-
- /** Amount of bitcoins spent by this transaction.
- @return sum of all outputs (note: does not include fees)
- */
- int64 GetValueOut() const
- {
- int64 nValueOut = 0;
- BOOST_FOREACH(const CTxOut& txout, vout)
- {
- nValueOut += txout.nValue;
- if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
- throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
- }
- return nValueOut;
- }
+/** Count ECDSA signature operations in pay-to-script-hash inputs.
- /** Amount of bitcoins coming in to this transaction
- Note that lightweight clients may not know anything besides the hash of previous transactions,
- so may not be able to calculate this.
-
- @param[in] mapInputs Map of previous transactions that have outputs we're spending
- @return Sum of value of all inputs (scriptSigs)
- */
- int64 GetValueIn(CCoinsViewCache& mapInputs) const;
-
- static bool AllowFree(double dPriority)
- {
- // Large (in bytes) low-priority (new, small-coin) transactions
- // need a fee.
- return dPriority > COIN * 144 / 250;
- }
-
- int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const;
-
- friend bool operator==(const CTransaction& a, const CTransaction& b)
- {
- return (a.nVersion == b.nVersion &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
- }
-
- friend bool operator!=(const CTransaction& a, const CTransaction& b)
- {
- return !(a == b);
- }
-
-
- std::string ToString() const
- {
- std::string str;
- str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
- GetHash().ToString().c_str(),
- nVersion,
- vin.size(),
- vout.size(),
- nLockTime);
- for (unsigned int i = 0; i < vin.size(); i++)
- str += " " + vin[i].ToString() + "\n";
- for (unsigned int i = 0; i < vout.size(); i++)
- str += " " + vout[i].ToString() + "\n";
- return str;
- }
-
- void print() const
- {
- printf("%s", ToString().c_str());
- }
-
-
- // Check whether all prevouts of this transaction are present in the UTXO set represented by view
- bool HaveInputs(CCoinsViewCache &view) const;
-
- // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
- // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
- // instead of being performed inline.
- bool CheckInputs(CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true,
- unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
- std::vector<CScriptCheck> *pvChecks = NULL) const;
-
- // Apply the effects of this transaction on the UTXO set represented by view
- bool UpdateCoins(CValidationState &state, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const;
-
- // Context-independent validity checks
- bool CheckTransaction(CValidationState &state) const;
+ @param[in] mapInputs Map of previous transactions that have outputs we're spending
+ @return maximum number of sigops required to validate this transaction's inputs
+ @see CTransaction::FetchInputs
+ */
+unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& mapInputs);
- // Try to accept this transaction into the memory pool
- bool AcceptToMemoryPool(CValidationState &state, bool fCheckInputs=true, bool fLimitFree = true, bool* pfMissingInputs=NULL);
-protected:
- static const CTxOut &GetOutputFor(const CTxIn& input, CCoinsViewCache& mapInputs);
-};
-
-/** wrapper for CTxOut that provides a more compact serialization */
-class CTxOutCompressor
+inline bool AllowFree(double dPriority)
{
-private:
- CTxOut &txout;
+ // Large (in bytes) low-priority (new, small-coin) transactions
+ // need a fee.
+ return dPriority > COIN * 144 / 250;
+}
-public:
- static uint64 CompressAmount(uint64 nAmount);
- static uint64 DecompressAmount(uint64 nAmount);
-
- CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
+// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
+// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
+// instead of being performed inline.
+bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true,
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
+ std::vector<CScriptCheck> *pvChecks = NULL);
- IMPLEMENT_SERIALIZE(({
- if (!fRead) {
- uint64 nVal = CompressAmount(txout.nValue);
- READWRITE(VARINT(nVal));
- } else {
- uint64 nVal = 0;
- READWRITE(VARINT(nVal));
- txout.nValue = DecompressAmount(nVal);
- }
- CScriptCompressor cscript(REF(txout.scriptPubKey));
- READWRITE(cscript);
- });)
-};
-
-/** Undo information for a CTxIn
- *
- * Contains the prevout's CTxOut being spent, and if this was the
- * last output of the affected transaction, its metadata as well
- * (coinbase or not, height, transaction version)
- */
-class CTxInUndo
-{
-public:
- CTxOut txout; // the txout data before being spent
- bool fCoinBase; // if the outpoint was the last unspent: whether it belonged to a coinbase
- unsigned int nHeight; // if the outpoint was the last unspent: its height
- int nVersion; // if the outpoint was the last unspent: its version
-
- CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nVersion(0) {}
- CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, unsigned int nHeightIn = 0, int nVersionIn = 0) : txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nVersion(nVersionIn) { }
-
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- return ::GetSerializeSize(VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion) +
- (nHeight > 0 ? ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion) : 0) +
- ::GetSerializeSize(CTxOutCompressor(REF(txout)), nType, nVersion);
- }
+// Apply the effects of this transaction on the UTXO set represented by view
+bool UpdateCoins(const CTransaction& tx, CCoinsViewCache &view, CTxUndo &txundo, int nHeight, const uint256 &txhash);
- template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
- ::Serialize(s, VARINT(nHeight*2+(fCoinBase ? 1 : 0)), nType, nVersion);
- if (nHeight > 0)
- ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Serialize(s, CTxOutCompressor(REF(txout)), nType, nVersion);
- }
+// Context-independent validity checks
+bool CheckTransaction(const CTransaction& tx, CValidationState& state);
- template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
- unsigned int nCode = 0;
- ::Unserialize(s, VARINT(nCode), nType, nVersion);
- nHeight = nCode / 2;
- fCoinBase = nCode & 1;
- if (nHeight > 0)
- ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
- ::Unserialize(s, REF(CTxOutCompressor(REF(txout))), nType, nVersion);
- }
-};
+/** Check for standard transaction types
+ @return True if all outputs (scriptPubKeys) use only standard transaction forms
+*/
+bool IsStandardTx(const CTransaction& tx);
-/** Undo information for a CTransaction */
-class CTxUndo
-{
-public:
- // undo information for all txins
- std::vector<CTxInUndo> vprevout;
+bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64 nBlockTime = 0);
- IMPLEMENT_SERIALIZE(
- READWRITE(vprevout);
- )
-};
+/** Amount of bitcoins spent by the transaction.
+ @return sum of all outputs (note: does not include fees)
+ */
+int64 GetValueOut(const CTransaction& tx);
/** Undo information for a CBlock */
class CBlockUndo
@@ -771,7 +352,7 @@ public:
// Write index header
unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(pchMessageStart) << nSize;
+ fileout << FLATDATA(Params().MessageStart()) << nSize;
// Write undo data
long fileOutPos = ftell(fileout);
@@ -822,254 +403,6 @@ public:
}
};
-/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
- *
- * Serialized format:
- * - VARINT(nVersion)
- * - VARINT(nCode)
- * - unspentness bitvector, for vout[2] and further; least significant byte first
- * - the non-spent CTxOuts (via CTxOutCompressor)
- * - VARINT(nHeight)
- *
- * The nCode value consists of:
- * - bit 1: IsCoinBase()
- * - bit 2: vout[0] is not spent
- * - bit 4: vout[1] is not spent
- * - The higher bits encode N, the number of non-zero bytes in the following bitvector.
- * - In case both bit 2 and bit 4 are unset, they encode N-1, as there must be at
- * least one non-spent output).
- *
- * Example: 0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e
- * <><><--------------------------------------------><---->
- * | \ | /
- * version code vout[1] height
- *
- * - version = 1
- * - code = 4 (vout[1] is not spent, and 0 non-zero bytes of bitvector follow)
- * - unspentness bitvector: as 0 non-zero bytes follow, it has length 0
- * - vout[1]: 835800816115944e077fe7c803cfa57f29b36bf87c1d35
- * * 8358: compact amount representation for 60000000000 (600 BTC)
- * * 00: special txout type pay-to-pubkey-hash
- * * 816115944e077fe7c803cfa57f29b36bf87c1d35: address uint160
- * - height = 203998
- *
- *
- * Example: 0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b
- * <><><--><--------------------------------------------------><----------------------------------------------><---->
- * / \ \ | | /
- * version code unspentness vout[4] vout[16] height
- *
- * - version = 1
- * - code = 9 (coinbase, neither vout[0] or vout[1] are unspent,
- * 2 (1, +1 because both bit 2 and bit 4 are unset) non-zero bitvector bytes follow)
- * - unspentness bitvector: bits 2 (0x04) and 14 (0x4000) are set, so vout[2+2] and vout[14+2] are unspent
- * - vout[4]: 86ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4ee
- * * 86ef97d579: compact amount representation for 234925952 (2.35 BTC)
- * * 00: special txout type pay-to-pubkey-hash
- * * 61b01caab50f1b8e9c50a5057eb43c2d9563a4ee: address uint160
- * - vout[16]: bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4
- * * bbd123: compact amount representation for 110397 (0.001 BTC)
- * * 00: special txout type pay-to-pubkey-hash
- * * 8c988f1a4a4de2161e0f50aac7f17e7f9555caa4: address uint160
- * - height = 120891
- */
-class CCoins
-{
-public:
- // whether transaction is a coinbase
- bool fCoinBase;
-
- // unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
- std::vector<CTxOut> vout;
-
- // at which height this transaction was included in the active block chain
- int nHeight;
-
- // version of the CTransaction; accesses to this value should probably check for nHeight as well,
- // as new tx version will probably only be introduced at certain heights
- int nVersion;
-
- // construct a CCoins from a CTransaction, at a given height
- CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) { }
-
- // empty constructor
- CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
-
- // remove spent outputs at the end of vout
- void Cleanup() {
- while (vout.size() > 0 && vout.back().IsNull())
- vout.pop_back();
- if (vout.empty())
- std::vector<CTxOut>().swap(vout);
- }
-
- void swap(CCoins &to) {
- std::swap(to.fCoinBase, fCoinBase);
- to.vout.swap(vout);
- std::swap(to.nHeight, nHeight);
- std::swap(to.nVersion, nVersion);
- }
-
- // equality test
- friend bool operator==(const CCoins &a, const CCoins &b) {
- return a.fCoinBase == b.fCoinBase &&
- a.nHeight == b.nHeight &&
- a.nVersion == b.nVersion &&
- a.vout == b.vout;
- }
- friend bool operator!=(const CCoins &a, const CCoins &b) {
- return !(a == b);
- }
-
- // calculate number of bytes for the bitmask, and its number of non-zero bytes
- // each bit in the bitmask represents the availability of one output, but the
- // availabilities of the first two outputs are encoded separately
- void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
- unsigned int nLastUsedByte = 0;
- for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
- bool fZero = true;
- for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
- if (!vout[2+b*8+i].IsNull()) {
- fZero = false;
- continue;
- }
- }
- if (!fZero) {
- nLastUsedByte = b + 1;
- nNonzeroBytes++;
- }
- }
- nBytes += nLastUsedByte;
- }
-
- bool IsCoinBase() const {
- return fCoinBase;
- }
-
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- unsigned int nSize = 0;
- unsigned int nMaskSize = 0, nMaskCode = 0;
- CalcMaskSize(nMaskSize, nMaskCode);
- bool fFirst = vout.size() > 0 && !vout[0].IsNull();
- bool fSecond = vout.size() > 1 && !vout[1].IsNull();
- assert(fFirst || fSecond || nMaskCode);
- unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
- // version
- nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion);
- // size of header code
- nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion);
- // spentness bitmask
- nSize += nMaskSize;
- // txouts themself
- for (unsigned int i = 0; i < vout.size(); i++)
- if (!vout[i].IsNull())
- nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion);
- // height
- nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion);
- return nSize;
- }
-
- template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
- unsigned int nMaskSize = 0, nMaskCode = 0;
- CalcMaskSize(nMaskSize, nMaskCode);
- bool fFirst = vout.size() > 0 && !vout[0].IsNull();
- bool fSecond = vout.size() > 1 && !vout[1].IsNull();
- assert(fFirst || fSecond || nMaskCode);
- unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0);
- // version
- ::Serialize(s, VARINT(this->nVersion), nType, nVersion);
- // header code
- ::Serialize(s, VARINT(nCode), nType, nVersion);
- // spentness bitmask
- for (unsigned int b = 0; b<nMaskSize; b++) {
- unsigned char chAvail = 0;
- for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++)
- if (!vout[2+b*8+i].IsNull())
- chAvail |= (1 << i);
- ::Serialize(s, chAvail, nType, nVersion);
- }
- // txouts themself
- for (unsigned int i = 0; i < vout.size(); i++) {
- if (!vout[i].IsNull())
- ::Serialize(s, CTxOutCompressor(REF(vout[i])), nType, nVersion);
- }
- // coinbase height
- ::Serialize(s, VARINT(nHeight), nType, nVersion);
- }
-
- template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
- unsigned int nCode = 0;
- // version
- ::Unserialize(s, VARINT(this->nVersion), nType, nVersion);
- // header code
- ::Unserialize(s, VARINT(nCode), nType, nVersion);
- fCoinBase = nCode & 1;
- std::vector<bool> vAvail(2, false);
- vAvail[0] = nCode & 2;
- vAvail[1] = nCode & 4;
- unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
- // spentness bitmask
- while (nMaskCode > 0) {
- unsigned char chAvail = 0;
- ::Unserialize(s, chAvail, nType, nVersion);
- for (unsigned int p = 0; p < 8; p++) {
- bool f = (chAvail & (1 << p)) != 0;
- vAvail.push_back(f);
- }
- if (chAvail != 0)
- nMaskCode--;
- }
- // txouts themself
- vout.assign(vAvail.size(), CTxOut());
- for (unsigned int i = 0; i < vAvail.size(); i++) {
- if (vAvail[i])
- ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion);
- }
- // coinbase height
- ::Unserialize(s, VARINT(nHeight), nType, nVersion);
- Cleanup();
- }
-
- // mark an outpoint spent, and construct undo information
- bool Spend(const COutPoint &out, CTxInUndo &undo) {
- if (out.n >= vout.size())
- return false;
- if (vout[out.n].IsNull())
- return false;
- undo = CTxInUndo(vout[out.n]);
- vout[out.n].SetNull();
- Cleanup();
- if (vout.size() == 0) {
- undo.nHeight = nHeight;
- undo.fCoinBase = fCoinBase;
- undo.nVersion = this->nVersion;
- }
- return true;
- }
-
- // mark a vout spent
- bool Spend(int nPos) {
- CTxInUndo undo;
- COutPoint out(0, nPos);
- return Spend(out, undo);
- }
-
- // check whether a particular output is still available
- bool IsAvailable(unsigned int nPos) const {
- return (nPos < vout.size() && !vout[nPos].IsNull());
- }
-
- // check whether the entire CCoins is spent
- // note that only !IsPruned() CCoins can be serialized
- bool IsPruned() const {
- BOOST_FOREACH(const CTxOut &out, vout)
- if (!out.IsNull())
- return false;
- return true;
- }
-};
/** Closure representing one script verification
* Note that this stores references to the spending transaction */
@@ -1144,7 +477,7 @@ public:
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
- bool AcceptToMemoryPool(bool fCheckInputs=true, bool fLimitFree=true);
+ bool AcceptToMemoryPool(bool fLimitFree=true);
};
@@ -1248,267 +581,33 @@ public:
};
-/** Nodes collect new transactions into a block, hash them into a hash tree,
- * and scan through nonce values to make the block's hash satisfy proof-of-work
- * requirements. When they solve the proof-of-work, they broadcast the block
- * to everyone and the block is added to the block chain. The first transaction
- * in the block is a special one that creates a new coin owned by the creator
- * of the block.
- */
-class CBlockHeader
-{
-public:
- // header
- static const int CURRENT_VERSION=2;
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
-
- CBlockHeader()
- {
- SetNull();
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(hashPrevBlock);
- READWRITE(hashMerkleRoot);
- READWRITE(nTime);
- READWRITE(nBits);
- READWRITE(nNonce);
- )
-
- void SetNull()
- {
- nVersion = CBlockHeader::CURRENT_VERSION;
- hashPrevBlock = 0;
- hashMerkleRoot = 0;
- nTime = 0;
- nBits = 0;
- nNonce = 0;
- }
-
- bool IsNull() const
- {
- return (nBits == 0);
- }
-
- uint256 GetHash() const
- {
- return Hash(BEGIN(nVersion), END(nNonce));
- }
-
- int64 GetBlockTime() const
- {
- return (int64)nTime;
- }
-
- void UpdateTime(const CBlockIndex* pindexPrev);
-};
-
-class CBlock : public CBlockHeader
-{
-public:
- // network and disk
- std::vector<CTransaction> vtx;
-
- // memory only
- mutable std::vector<uint256> vMerkleTree;
-
- CBlock()
- {
- SetNull();
- }
-
- CBlock(const CBlockHeader &header)
- {
- SetNull();
- *((CBlockHeader*)this) = header;
- }
-
- IMPLEMENT_SERIALIZE
- (
- READWRITE(*(CBlockHeader*)this);
- READWRITE(vtx);
- )
-
- void SetNull()
- {
- CBlockHeader::SetNull();
- vtx.clear();
- vMerkleTree.clear();
- }
-
- CBlockHeader GetBlockHeader() const
- {
- CBlockHeader block;
- block.nVersion = nVersion;
- block.hashPrevBlock = hashPrevBlock;
- block.hashMerkleRoot = hashMerkleRoot;
- block.nTime = nTime;
- block.nBits = nBits;
- block.nNonce = nNonce;
- return block;
- }
-
- uint256 BuildMerkleTree() const
- {
- vMerkleTree.clear();
- BOOST_FOREACH(const CTransaction& tx, vtx)
- vMerkleTree.push_back(tx.GetHash());
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- for (int i = 0; i < nSize; i += 2)
- {
- int i2 = std::min(i+1, nSize-1);
- vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
- BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
- }
- j += nSize;
- }
- return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
- }
-
- const uint256 &GetTxHash(unsigned int nIndex) const {
- assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
- assert(nIndex < vtx.size());
- return vMerkleTree[nIndex];
- }
-
- std::vector<uint256> GetMerkleBranch(int nIndex) const
- {
- if (vMerkleTree.empty())
- BuildMerkleTree();
- std::vector<uint256> vMerkleBranch;
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- int i = std::min(nIndex^1, nSize-1);
- vMerkleBranch.push_back(vMerkleTree[j+i]);
- nIndex >>= 1;
- j += nSize;
- }
- return vMerkleBranch;
- }
-
- static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
- {
- if (nIndex == -1)
- return 0;
- BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
- {
- if (nIndex & 1)
- hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
- else
- hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
- nIndex >>= 1;
- }
- return hash;
- }
-
- bool WriteToDisk(CDiskBlockPos &pos)
- {
- // Open history file to append
- CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
- if (!fileout)
- return error("CBlock::WriteToDisk() : OpenBlockFile failed");
-
- // Write index header
- unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(pchMessageStart) << nSize;
- // Write block
- long fileOutPos = ftell(fileout);
- if (fileOutPos < 0)
- return error("CBlock::WriteToDisk() : ftell failed");
- pos.nPos = (unsigned int)fileOutPos;
- fileout << *this;
+/** Functions for disk access for blocks */
+bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
- // Flush stdio buffers and commit to disk before returning
- fflush(fileout);
- if (!IsInitialBlockDownload())
- FileCommit(fileout);
- return true;
- }
+/** Functions for validating blocks and updating the block tree */
- bool ReadFromDisk(const CDiskBlockPos &pos)
- {
- SetNull();
+/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
+ * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
+ * will be true if no problems were found. Otherwise, the return value will be false in case
+ * of problems. Note that in any case, coins may be modified. */
+bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
- // Open history file to read
- CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
- if (!filein)
- return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
+// Apply the effects of this block (with given index) on the UTXO set represented by coins
+bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
- // Read block
- try {
- filein >> *this;
- }
- catch (std::exception &e) {
- return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
- }
-
- // Check the header
- if (!CheckProofOfWork(GetHash(), nBits))
- return error("CBlock::ReadFromDisk() : errors in block header");
-
- return true;
- }
-
-
-
- void print() const
- {
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
- GetHash().ToString().c_str(),
- nVersion,
- hashPrevBlock.ToString().c_str(),
- hashMerkleRoot.ToString().c_str(),
- nTime, nBits, nNonce,
- vtx.size());
- for (unsigned int i = 0; i < vtx.size(); i++)
- {
- printf(" ");
- vtx[i].print();
- }
- printf(" vMerkleTree: ");
- for (unsigned int i = 0; i < vMerkleTree.size(); i++)
- printf("%s ", vMerkleTree[i].ToString().c_str());
- printf("\n");
- }
-
-
- /** Undo the effects of this block (with given index) on the UTXO set represented by coins.
- * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
- * will be true if no problems were found. Otherwise, the return value will be false in case
- * of problems. Note that in any case, coins may be modified. */
- bool DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool *pfClean = NULL);
-
- // Apply the effects of this block (with given index) on the UTXO set represented by coins
- bool ConnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false);
-
- // Read a block from disk
- bool ReadFromDisk(const CBlockIndex* pindex);
-
- // Add this block to the block index, and if necessary, switch the active block chain to this
- bool AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos);
-
- // Context-independent validity checks
- bool CheckBlock(CValidationState &state, bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
-
- // Store block on disk
- // if dbp is provided, the file is known to already reside on disk
- bool AcceptBlock(CValidationState &state, CDiskBlockPos *dbp = NULL);
-};
+// Add this block to the block index, and if necessary, switch the active block chain to this
+bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos);
+// Context-independent validity checks
+bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
+// Store block on disk
+// if dbp is provided, the file is known to already reside on disk
+bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp = NULL);
@@ -1589,10 +688,8 @@ enum BlockStatus {
/** The block chain is a tree shaped structure starting with the
* genesis block at the root, with each block potentially having multiple
- * candidates to be the next block. pprev and pnext link a path through the
- * main/longest chain. A blockindex may have multiple pprev pointing back
- * to it, but pnext will only point forward to the longest branch, or will
- * be null if the block is not part of the longest chain.
+ * candidates to be the next block. A blockindex may have multiple pprev pointing
+ * to it, but at most one of them can be part of the currently active branch.
*/
class CBlockIndex
{
@@ -1603,9 +700,6 @@ public:
// pointer to the index of the predecessor of this block
CBlockIndex* pprev;
- // (memory only) pointer to the index of the *active* successor of this block
- CBlockIndex* pnext;
-
// height of the entry in the chain. The genesis block has height 0
int nHeight;
@@ -1643,7 +737,6 @@ public:
{
phashBlock = NULL;
pprev = NULL;
- pnext = NULL;
nHeight = 0;
nFile = 0;
nDataPos = 0;
@@ -1664,7 +757,6 @@ public:
{
phashBlock = NULL;
pprev = NULL;
- pnext = NULL;
nHeight = 0;
nFile = 0;
nDataPos = 0;
@@ -1733,7 +825,11 @@ public:
bool IsInMainChain() const
{
- return (pnext || this == pindexBest);
+ return nHeight < (int)vBlockIndexByHeight.size() && vBlockIndexByHeight[nHeight] == this;
+ }
+
+ CBlockIndex *GetNextInMainChain() const {
+ return nHeight+1 >= (int)vBlockIndexByHeight.size() ? NULL : vBlockIndexByHeight[nHeight+1];
}
bool CheckIndex() const
@@ -1762,9 +858,9 @@ public:
const CBlockIndex* pindex = this;
for (int i = 0; i < nMedianTimeSpan/2; i++)
{
- if (!pindex->pnext)
+ if (!pindex->GetNextInMainChain())
return GetBlockTime();
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
}
return pindex->GetMedianTimePast();
}
@@ -1779,7 +875,7 @@ public:
std::string ToString() const
{
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
- pprev, pnext, nHeight,
+ pprev, GetNextInMainChain(), nHeight,
hashMerkleRoot.ToString().c_str(),
GetBlockHash().ToString().c_str());
}
@@ -1934,22 +1030,14 @@ class CBlockLocator
protected:
std::vector<uint256> vHave;
public:
-
- CBlockLocator()
- {
- }
+ CBlockLocator() {}
explicit CBlockLocator(const CBlockIndex* pindex)
{
Set(pindex);
}
- explicit CBlockLocator(uint256 hashBlock)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
- }
+ explicit CBlockLocator(uint256 hashBlock);
CBlockLocator(const std::vector<uint256>& vHaveIn)
{
@@ -1973,83 +1061,16 @@ public:
return vHave.empty();
}
- void Set(const CBlockIndex* pindex)
- {
- vHave.clear();
- int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
-
- // Exponentially larger steps back
- for (int i = 0; pindex && i < nStep; i++)
- pindex = pindex->pprev;
- if (vHave.size() > 10)
- nStep *= 2;
- }
- vHave.push_back(hashGenesisBlock);
- }
-
- int GetDistanceBack()
- {
- // Retrace how far back it was in the sender's branch
- int nDistance = 0;
- int nStep = 1;
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return nDistance;
- }
- nDistance += nStep;
- if (nDistance > 10)
- nStep *= 2;
- }
- return nDistance;
- }
-
- CBlockIndex* GetBlockIndex()
- {
- // Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return pindex;
- }
- }
- return pindexGenesisBlock;
- }
-
- uint256 GetBlockHash()
- {
- // Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- return hash;
- }
- }
- return hashGenesisBlock;
- }
-
- int GetHeight()
- {
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
- }
+ /** Given a block initialises the locator to that point in the chain. */
+ void Set(const CBlockIndex* pindex);
+ /** Returns the distance in blocks this locator is from our chain head. */
+ int GetDistanceBack();
+ /** Returns the first best-chain block the locator contains. */
+ CBlockIndex* GetBlockIndex();
+ /** Returns the hash of the first best chain block the locator contains. */
+ uint256 GetBlockHash();
+ /** Returns the height of the first best chain block the locator has. */
+ int GetHeight();
};
@@ -2066,7 +1087,7 @@ public:
std::map<uint256, CTransaction> mapTx;
std::map<COutPoint, CInPoint> mapNextTx;
- bool accept(CValidationState &state, CTransaction &tx, bool fCheckInputs, bool fLimitFree, bool* pfMissingInputs);
+ bool accept(CValidationState &state, CTransaction &tx, bool fLimitFree, bool* pfMissingInputs);
bool addUnchecked(const uint256& hash, CTransaction &tx);
bool remove(const CTransaction &tx, bool fRecursive = false);
bool removeConflicts(const CTransaction &tx);
@@ -2184,6 +1205,21 @@ public:
// Calculate the size of the cache (in number of transactions)
unsigned int GetCacheSize();
+ /** Amount of bitcoins coming in to a transaction
+ Note that lightweight clients may not know anything besides the hash of previous transactions,
+ so may not be able to calculate this.
+
+ @param[in] tx transaction for which we are checking input total
+ @return Sum of value of all inputs (scriptSigs)
+ @see CTransaction::FetchInputs
+ */
+ int64 GetValueIn(const CTransaction& tx);
+
+ // Check whether all prevouts of the transaction are present in the UTXO set represented by this view
+ bool HaveInputs(const CTransaction& tx);
+
+ const CTxOut &GetOutputFor(const CTxIn& input);
+
private:
std::map<uint256,CCoins>::iterator FetchCoins(const uint256 &txid);
};
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 7719cd2637..26d541664e 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -71,7 +71,9 @@ OBJS= \
obj/key.o \
obj/db.o \
obj/init.o \
+ obj/bitcoind.o \
obj/keystore.o \
+ obj/core.o \
obj/main.o \
obj/net.o \
obj/protocol.o \
@@ -91,7 +93,8 @@ OBJS= \
obj/hash.o \
obj/bloom.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind.exe
@@ -116,7 +119,7 @@ TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
obj-test/%.o: test/%.cpp $(HEADERS)
$(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -o $@ $<
-test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
+test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
$(CXX) $(xCXXFLAGS) $(xLDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 8b5a5dccd9..3659f52040 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -79,7 +79,9 @@ OBJS= \
obj/key.o \
obj/db.o \
obj/init.o \
+ obj/bitcoind.o \
obj/keystore.o \
+ obj/core.o \
obj/main.o \
obj/net.o \
obj/protocol.o \
@@ -99,7 +101,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind.exe
@@ -127,7 +130,7 @@ TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
obj-test/%.o: test/%.cpp $(HEADERS)
$(CXX) -c $(TESTDEFS) $(CFLAGS) -o $@ $<
-test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
+test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
$(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework$(BOOST_SUFFIX) $(LIBS)
clean:
diff --git a/src/makefile.osx b/src/makefile.osx
index 50279fdb05..269460c1ba 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -82,7 +82,9 @@ OBJS= \
obj/key.o \
obj/db.o \
obj/init.o \
+ obj/bitcoind.o \
obj/keystore.o \
+ obj/core.o \
obj/main.o \
obj/net.o \
obj/protocol.o \
@@ -102,7 +104,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
ifndef USE_UPNP
override USE_UPNP = -
@@ -162,7 +165,7 @@ obj-test/%.o: test/%.cpp
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
-test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
+test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
$(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) $(TESTLIBS)
clean:
diff --git a/src/makefile.unix b/src/makefile.unix
index 8110235647..f17de05cb9 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -121,7 +121,9 @@ OBJS= \
obj/key.o \
obj/db.o \
obj/init.o \
+ obj/bitcoind.o \
obj/keystore.o \
+ obj/core.o \
obj/main.o \
obj/net.o \
obj/protocol.o \
@@ -141,7 +143,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind
@@ -187,7 +190,7 @@ obj-test/%.o: test/%.cpp
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
-test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
+test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o obj/bitcoind.o,$(OBJS:obj/%=obj/%))
$(LINK) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ $(TESTLIBS) $(xLDFLAGS) $(LIBS)
clean:
diff --git a/src/net.cpp b/src/net.cpp
index 54ed1d9b51..5418c3de40 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -3,9 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "db.h"
#include "net.h"
-#include "init.h"
+#include "core.h"
#include "addrman.h"
#include "ui_interface.h"
#include "script.h"
@@ -21,6 +22,9 @@
#include <miniupnpc/upnperrors.h>
#endif
+// Dump addresses to peers.dat every 15 minutes (900s)
+#define DUMP_ADDRESSES_INTERVAL 900
+
using namespace std;
using namespace boost;
@@ -68,6 +72,10 @@ CCriticalSection cs_vAddedNodes;
static CSemaphore *semOutbound = NULL;
+// Signals for message handling
+static CNodeSignals g_signals;
+CNodeSignals& GetNodeSignals() { return g_signals; }
+
void AddOneShot(string strDest)
{
LOCK(cs_vOneShots);
@@ -76,18 +84,7 @@ void AddOneShot(string strDest)
unsigned short GetListenPort()
{
- return (unsigned short)(GetArg("-port", GetDefaultPort()));
-}
-
-void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
-{
- // Filter out duplicate requests
- if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
- return;
- pindexLastGetBlocksBegin = pindexBegin;
- hashLastGetBlocksEnd = hashEnd;
-
- PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
+ return (unsigned short)(GetArg("-port", Params().GetDefaultPort()));
}
// find 'best' local address for a particular peer
@@ -396,11 +393,8 @@ bool GetMyExternalIP(CNetAddr& ipRet)
return false;
}
-void ThreadGetMyExternalIP(void* parg)
+void ThreadGetMyExternalIP()
{
- // Make this thread recognisable as the external IP detection thread
- RenameThread("bitcoin-ext-ip");
-
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
@@ -474,7 +468,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
// Connect
SOCKET hSocket;
- if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
+ if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
{
addrman.Attempt(addrConnect);
@@ -543,7 +537,7 @@ void CNode::PushVersion()
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
- nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
+ nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
}
@@ -1158,7 +1152,7 @@ void MapPort(bool fUseUPnP)
upnp_thread->join();
delete upnp_thread;
}
- upnp_thread = new boost::thread(boost::bind(&TraceThread<boost::function<void()> >, "upnp", &ThreadMapPort));
+ upnp_thread = new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort));
}
else if (upnp_thread) {
upnp_thread->interrupt();
@@ -1180,53 +1174,31 @@ void MapPort(bool)
-
-
-
-// DNS seeds
-// Each pair gives a source name and a seed name.
-// The first name is used as information source for addrman.
-// The second name should resolve to a list of seed addresses.
-static const char *strMainNetDNSSeed[][2] = {
- {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"},
- {"bluematt.me", "dnsseed.bluematt.me"},
- {"dashjr.org", "dnsseed.bitcoin.dashjr.org"},
- {"xf2.org", "bitseed.xf2.org"},
- {NULL, NULL}
-};
-
-static const char *strTestNetDNSSeed[][2] = {
- {"bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"},
- {"bluematt.me", "testnet-seed.bluematt.me"},
- {NULL, NULL}
-};
-
void ThreadDNSAddressSeed()
{
- static const char *(*strDNSSeed)[2] = fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed;
-
+ const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
int found = 0;
printf("Loading addresses from DNS seeds (could take a while)\n");
- for (unsigned int seed_idx = 0; strDNSSeed[seed_idx][0] != NULL; seed_idx++) {
+ BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
if (HaveNameProxy()) {
- AddOneShot(strDNSSeed[seed_idx][1]);
+ AddOneShot(seed.host);
} else {
- vector<CNetAddr> vaddr;
+ vector<CNetAddr> vIPs;
vector<CAddress> vAdd;
- if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
+ if (LookupHost(seed.host.c_str(), vIPs))
{
- BOOST_FOREACH(CNetAddr& ip, vaddr)
+ BOOST_FOREACH(CNetAddr& ip, vIPs)
{
int nOneDay = 24*3600;
- CAddress addr = CAddress(CService(ip, GetDefaultPort()));
+ CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
}
}
- addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
+ addrman.Add(vAdd, CNetAddr(seed.name, true));
}
}
@@ -1244,85 +1216,6 @@ void ThreadDNSAddressSeed()
-unsigned int pnSeed[] =
-{
- 0xe473042e, 0xb177f2ad, 0xd63f3fb2, 0xf864f736, 0x44a23ac7, 0xcf6d9650, 0xd648042e, 0x0536f447,
- 0x3c654ed0, 0x3e16a5bc, 0xa38e09b0, 0xdfae795b, 0xabfeca5b, 0x94ad7840, 0xf3b9f1c7, 0xbe70e0ad,
- 0x3bbd09b0, 0x8d0c7dd5, 0x3b2a7332, 0x1a06175e, 0x581f175e, 0xca0d2dcc, 0x0fdbc658, 0xcf591ec7,
- 0x295a12b2, 0xb4707bce, 0x68bb09b0, 0x4e735747, 0x89709553, 0x05a7814e, 0x5b8ec658, 0x402c5512,
- 0xe80d0905, 0x17681a5e, 0xc02aa748, 0x9f811741, 0x5f321cb0, 0x23e1ee47, 0xaf7f170c, 0xaa240ab0,
- 0xedea6257, 0x76106bc1, 0x2cf310cc, 0x08612acb, 0x9c682e4e, 0x8e963c6c, 0x443c795b, 0x22e246b8,
- 0xfa1f2dcc, 0x90118140, 0x3821042e, 0x33c3fd2e, 0x10046d5b, 0x40d14b3e, 0x7fb8f8ce, 0x67696550,
- 0xeeecbe58, 0x4f341745, 0x46b8fbd5, 0xc8463932, 0x6b73e862, 0x4c715932, 0x4a6785d5, 0xce3a64c2,
- 0xde9604c7, 0x9b06884f, 0x18002a45, 0xea9bc345, 0xc4f1c658, 0xe475c1c7, 0xdd3e795b, 0x9722175e,
- 0x34562f4e, 0x66c46e4e, 0x40bb1243, 0x7d9171d0, 0x17b8dbd5, 0x63cbfd2e, 0x1a08b8d8, 0x6175a73b,
- 0x228d2660, 0x8627c658, 0x9c566644, 0x38cca5bc, 0x3089de5b, 0x92e25f5d, 0xa393f73f, 0xcc92dc3e,
- 0x27487446, 0x62cbfd2e, 0x9d983b45, 0xf72a09b0, 0xf75f042e, 0x6434bb6a, 0xb29e77d8, 0x19be4fd9,
- 0x76443243, 0x9dd72645, 0x694cef43, 0x89c2efd5, 0x5f1c5058, 0x46c6e45b, 0xe1391b40, 0x77ccefd5,
- 0x472e5a6d, 0x85709553, 0xdd4f5d4c, 0x64ef5a46, 0x7f0ae502, 0xcf08d850, 0x3460042e, 0xeafa2d42,
- 0x793c9044, 0x9d094746, 0x1ab9b153, 0xbfe9a5bc, 0x34771fb0, 0xb7722e32, 0x1168964b, 0x19b06ab8,
- 0x19243b25, 0x13188045, 0xb4070905, 0x728ebb5d, 0x44f24ac8, 0xa317fead, 0x642f6a57, 0x3d951f32,
- 0x3d312e4e, 0xfac4d048, 0xefc4dd50, 0x52b9f1c7, 0xc14d3cc3, 0x0219ea44, 0x3b79d058, 0xfa217242,
- 0x39c80647, 0xfb697252, 0x1d495a42, 0x0aa81f4e, 0x58249ab8, 0xe6a8e6c3, 0x2bc4dad8, 0x85963c6c,
- 0xa4ce09b0, 0x2005f536, 0x5cc2703e, 0x1992de43, 0x74e86b4c, 0xe7085653, 0xf5e15a51, 0xb4872b60,
- 0x29e2b162, 0xa07ea053, 0x8229fd18, 0x4562ec4d, 0x8dec814e, 0x36cfa4cf, 0x96461032, 0x3c8770de,
- 0xd10a1f5f, 0x95934641, 0x97cd65d0, 0x2e35324a, 0x2566ba1f, 0x1ca1a9d1, 0xb808b8d5, 0xf9a24a5d,
- 0xafc8d431, 0xe4b8d9b2, 0x0f5321b2, 0x330bc658, 0x74b347ce, 0x972babd5, 0x044f7d4f, 0x06562f4e,
- 0x8b8d3c6c, 0x3507c658, 0xe4174e4d, 0xf1c009b0, 0x52249ab8, 0x27211772, 0xf6a9ba59, 0x7a391b40,
- 0x855dc6c0, 0x291f20b2, 0xe29bc345, 0x90963c6c, 0x0af70732, 0x4242a91f, 0x4c531d48, 0xa32df948,
- 0x627e3044, 0x65be1f54, 0x1a0cbf83, 0x6a443532, 0x8d5f1955, 0xbafa8132, 0x3534bdd5, 0xca019dd9,
- 0x8a0d9332, 0x5584e7d8, 0x7cd1f25e, 0xeabe3fb2, 0x2945d0d1, 0x46415718, 0x70d6042e, 0x99eb76d0,
- 0x9ece09b0, 0xb3777418, 0x5e5e91d9, 0x237a3ab0, 0xf512b62e, 0x45dec347, 0x59b7f862, 0x4c443b25,
- 0x3cc6484b, 0x9a8ec6d1, 0x021eea44, 0xc9483944, 0xfd567e32, 0xfd204bb2, 0xc5330bcc, 0x5202894e,
- 0xf9e309b0, 0x4cc17557, 0xdb9064ae, 0xe19e77d8, 0x25857f60, 0xeb4a15ad, 0x1f47f554, 0xea4472d9,
- 0xd20de593, 0xf5733b25, 0x11892b54, 0x5729d35f, 0xe6188cd1, 0x488b132e, 0x541c534a, 0xa8e854ae,
- 0xa255a66c, 0x33688763, 0xc6629ac6, 0xc20a6265, 0xcd92a059, 0x72029d3b, 0x4c298f5e, 0x51452e4e,
- 0xbb065058, 0x15fd2dcc, 0xf40c135e, 0x615a0bad, 0x0c6a6805, 0x4971a7ad, 0x17f2a5d5, 0xf8babf47,
- 0xb61f50ad, 0x4e1451b1, 0xf72d9252, 0x5c2abe58, 0xbd987c61, 0x084ae5cf, 0x20781fb0, 0x38b0f160,
- 0x18aac705, 0x14f86dc1, 0x5556f481, 0x0a36c144, 0xeb446e4c, 0x2c1c0d6c, 0xbd0ff860, 0x869f92db,
- 0x36c94f4c, 0x05502444, 0x148fe55b, 0xd5301e59, 0xd57a8f45, 0x110dc04a, 0x8670fc36, 0xee733b25,
- 0xca56f481, 0x2a5c3bae, 0x844b0905, 0x1e51fe53, 0x0241c244, 0x59c0614e, 0x94e70a55, 0x7312fead,
- 0xb735be44, 0xa55d0905, 0x2f63962e, 0x14a4e15b, 0x63f8f05c, 0x62d0d262, 0x3cab41ad, 0x87f1b1cb,
- 0x018da6b8, 0xb3967dd5, 0xcb56f481, 0x685ad718, 0x3b4aeeca, 0x8d106bc1, 0x51180905, 0x72660f48,
- 0x1521a243, 0x5b56f481, 0x6390e560, 0xdd61464e, 0x58353b25, 0x553fc062, 0x27c45d59, 0xacc62e4e,
- 0x0d5a1cd9, 0x7f65f442, 0xbdeef660, 0xf1bd1855, 0xf8473cae, 0x13b120b2, 0x442440d0, 0x53fd4352,
- 0xa305fc57, 0x458be84d, 0x639ce1c3, 0xebaaee47, 0x95e2c247, 0xf056f481, 0x6256f481, 0x1d87c65e,
- 0x0a453418, 0x5beb175e, 0xd64f1618, 0xc360795b, 0x2fbf5753, 0xa8c58e53, 0x651cec52, 0x9d37b043,
- 0x124a9758, 0x5242e4a9, 0x89913c6c, 0x880efe2e, 0x2f2f2f0c, 0x72b26751, 0x2896e46d, 0x80f4166c,
- 0x320d59ad, 0xc50151d0, 0x11a8aa43, 0xccf56057, 0x5fbad118, 0x4719b151, 0x2b5f4bc0, 0x4d7a4a50,
- 0xad06e047, 0x62ef5a46, 0x5aebde58, 0xdf7aa66c, 0x851acb50, 0x66b9a559, 0x3e9bb153, 0xcc512f2e,
- 0xc073b08e, 0xd519be58, 0xe981ea4d, 0x12fd50cb, 0x378739ad, 0x06683cae, 0xa22310b2, 0xc185c705,
- 0x8741b545, 0xa26c8318, 0x22d5bc43, 0x39201ec0, 0x68581e3e, 0xdc9bcf62, 0xd508cc82, 0xb149675b,
- 0x4c9609b0, 0x84feb84c, 0x08291e2e, 0xfd2253b2, 0x1fd269c1, 0xc9483932, 0x4d641fb0, 0x7d37c918,
- 0xa9de20ad, 0x77e2d655, 0x6d421b59, 0xd7668f80, 0xced09b62, 0xa9e5a5bc, 0xa4074e18, 0x60fc5ecc,
- 0x01300148, 0x68062444, 0xb4224847, 0xed3aa443, 0xb772fb43, 0x9f56f481, 0x220dfd18, 0x8e1c3d6c,
- 0xc44f09b0, 0x7df2bb73, 0xe22fb844, 0xea534242, 0xb6a755d4, 0xa036654b, 0x138ece5b, 0xda65d3c3,
- 0x955871bc, 0x792124b0, 0xfc82594c, 0x851d494b, 0x2c7aee47, 0x26af46b8, 0x1416252e, 0xa8abb944,
- 0x36c49d25, 0x674f645d, 0x363646b8, 0x9e1a2942, 0x66d0c154, 0xc6c2a545, 0x3570f2ad, 0xe7d547c7,
- 0x7d104932, 0x18cb9c18, 0x1dcfa4cf, 0xd156f481, 0x2a02b91f, 0x3eeb3fa8, 0xcac4175e, 0x34146d42,
- 0x994c4d46, 0x5666f440, 0x85d6713e, 0x5ecb296c, 0x0ea0ae46, 0x87e69f42, 0xc58409b0, 0x1f3436ae,
- 0x21dc6a57, 0x4ad1cd42, 0xfb8c1a4c, 0x52d3dab2, 0x3769894b, 0xb52f1c62, 0x3677916d, 0x82b3fe57,
- 0x493d4ac6, 0x9f963c6c, 0x5d91ff60, 0x458e0dad, 0xa49d0947, 0x491a3e18, 0x4aadcd5b, 0x0e46494b,
- 0x1d1610ad, 0x1a10af5d, 0x4956f481, 0x207a3eae, 0x77e73244, 0xfa3b8742, 0x3261fc36, 0xfcebf536,
- 0x1662e836, 0xf655f636, 0xa2dbd0ad, 0x23036693, 0x30448432, 0xa2b03463, 0x30730344, 0x8e4a6882,
- 0x0c50a1cb, 0xc8d8c06b, 0xc9cd6191, 0xf443db50, 0xa9553c50, 0x23145847, 0xc35da66c, 0x29c12a60,
- 0x55c2b447, 0x7434f75c, 0x61660640, 0xde2a7018, 0xc639494c, 0x1c306fce, 0x19b89244, 0xd29a6462,
- 0x462cd1b2, 0x29902f44, 0x2817fa53, 0x21a30905, 0x7777ae46, 0x288443a1, 0x7bee5148, 0xc2a8b043,
- 0xf5c3d35f, 0x2311ef84, 0x57de08a4, 0x6b221bb2, 0xf2625846, 0x4b9e09b0, 0xa24f880e, 0x22b11447,
- 0xb3a0c744, 0x919e77d8, 0xec8b64ae, 0xff5c8d45, 0x7b15b484, 0x32679a5f, 0xba80b62e, 0x05c25c61,
- 0x60014746, 0x5e8fb04c, 0xe67c0905, 0x4329c658, 0xac8fe555, 0xf875e647, 0x67406386, 0x35ceea18,
- 0xbb79484b, 0xd7b9fa62, 0x238209b0, 0x208a1d32, 0x9630995e, 0x039c1318, 0x6e48006c, 0x60582344,
- 0xadbb0150, 0x853fd462, 0x03772e4e, 0x652ce960, 0x49b630ad, 0x9993af43, 0x3735b34b, 0x548a07d9,
- 0x55a44aad, 0xa23d1bcc, 0xfdbb2f4e, 0x530b24a0, 0x0a44b451, 0x6827c657, 0x1f66494b, 0x4e680a47,
- 0x77e7b747, 0xa5eb3fa8, 0x6649764a, 0xd4e76c4b, 0x2c691fb0, 0xf1292e44, 0xc6d6c774, 0x85d23775,
- 0x28275f4d, 0x259ae46d, 0x02424e81, 0x5f16be58, 0xe707c658, 0x49eae5c7, 0xd5d147ad, 0x9a7abdc3,
- 0xe8ac7fc7, 0x84ec3aae, 0xc24942d0, 0x294aa318, 0x08ac3d18, 0x8894042e, 0xb24609b0, 0x9bcaab58,
- 0xc400f712, 0xd5c512b8, 0x2c02cc62, 0x25080fd8, 0xed74a847, 0x18a5ec5e, 0x9850ec6d, 0xf8909758,
- 0x7f56f481, 0x4496f23c, 0xae27784f, 0xcb7cd93e, 0x06e32860, 0x50b9a84f, 0x3660434a, 0x09161f5f,
- 0x900486bc, 0x08055459, 0xe7ec1017, 0x7e39494c, 0x4f443b25, 0x14751a8a, 0x717d03d4, 0xbd0e24d8,
- 0x054b6f56, 0x854c496c, 0xd92a454a, 0xc39bd054, 0x6093614b, 0x9dbad754, 0x5bf0604a, 0x99f22305
-};
-
void DumpAddresses()
{
int64 nStart = GetTimeMillis();
@@ -1384,24 +1277,14 @@ void ThreadOpenConnections()
CSemaphoreGrant grant(*semOutbound);
boost::this_thread::interruption_point();
- // Add seed nodes if IRC isn't working
- if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
- {
- std::vector<CAddress> vAdd;
- for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
- {
- // 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;
- struct in_addr ip;
- memcpy(&ip, &pnSeed[i], sizeof(ip));
- CAddress addr(CService(ip, GetDefaultPort()));
- addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
- vAdd.push_back(addr);
+ // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
+ if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
+ static bool done = false;
+ if (!done) {
+ printf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
+ addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
+ done = true;
}
- addrman.Add(vAdd, CNetAddr("127.0.0.1"));
}
//
@@ -1450,7 +1333,7 @@ void ThreadOpenConnections()
continue;
// do not allow non-default ports, unless after 50 invalid addresses selected already
- if (addr.GetPort() != GetDefaultPort() && nTries < 50)
+ if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
addrConnect = addr;
@@ -1500,7 +1383,7 @@ void ThreadOpenAddedConnections()
BOOST_FOREACH(string& strAddNode, lAddresses)
{
vector<CService> vservNode(0);
- if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
+ if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
{
lservAddressesToAdd.push_back(vservNode);
{
@@ -1574,11 +1457,6 @@ void static StartSync(const vector<CNode*> &vNodes) {
CNode *pnodeNewSync = NULL;
double dBestScore = 0;
- // fImporting and fReindex are accessed out of cs_main here, but only
- // as an optimization - they are checked again in SendMessages.
- if (fImporting || fReindex)
- return;
-
// Iterate over all nodes
BOOST_FOREACH(CNode* pnode, vNodes) {
// check preconditions for allowing a sync
@@ -1635,7 +1513,7 @@ void ThreadMessageHandler()
{
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
if (lockRecv)
- if (!ProcessMessages(pnode))
+ if (!g_signals.ProcessMessages(pnode))
pnode->CloseSocketDisconnect();
}
boost::this_thread::interruption_point();
@@ -1644,7 +1522,7 @@ void ThreadMessageHandler()
{
TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend)
- SendMessages(pnode, pnode == pnodeTrickle);
+ g_signals.SendMessages(pnode, pnode == pnodeTrickle);
}
boost::this_thread::interruption_point();
}
@@ -1812,7 +1690,7 @@ void static Discover()
// Don't use external IPv4 discovery, when -onlynet="IPv6"
if (!IsLimited(NET_IPV4))
- NewThread(ThreadGetMyExternalIP, NULL);
+ boost::thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
}
void StartNode(boost::thread_group& threadGroup)
@@ -1835,7 +1713,7 @@ void StartNode(boost::thread_group& threadGroup)
if (!GetBoolArg("-dnsseed", true))
printf("DNS seeding disabled\n");
else
- threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "dnsseed", &ThreadDNSAddressSeed));
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
#ifdef USE_UPNP
// Map ports with UPnP
@@ -1855,15 +1733,13 @@ void StartNode(boost::thread_group& threadGroup)
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
// Dump network addresses
- threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
+ threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
}
bool StopNode()
{
printf("StopNode()\n");
- GenerateBitcoins(false, NULL);
MapPort(false);
- nTransactionsUpdated++;
if (semOutbound)
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
semOutbound->post();
diff --git a/src/net.h b/src/net.h
index af66eed070..e75fe48f64 100644
--- a/src/net.h
+++ b/src/net.h
@@ -8,6 +8,7 @@
#include <deque>
#include <boost/array.hpp>
#include <boost/foreach.hpp>
+#include <boost/signals2/signal.hpp>
#include <openssl/rand.h>
#ifndef WIN32
@@ -22,6 +23,9 @@
#include "hash.h"
#include "bloom.h"
+/** The maximum number of entries in an 'inv' protocol message */
+static const unsigned int MAX_INV_SZ = 50000;
+
class CNode;
class CBlockIndex;
extern int nBestHeight;
@@ -45,6 +49,16 @@ void StartNode(boost::thread_group& threadGroup);
bool StopNode();
void SocketSendData(CNode *pnode);
+// Signals for message handling
+struct CNodeSignals
+{
+ boost::signals2::signal<bool (CNode*)> ProcessMessages;
+ boost::signals2::signal<bool (CNode*, bool)> SendMessages;
+};
+
+CNodeSignals& GetNodeSignals();
+
+
enum
{
LOCAL_NONE, // unknown
@@ -600,7 +614,6 @@ public:
}
}
- void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
bool IsSubscribed(unsigned int nChannel);
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel);
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 88bbe49afd..745b4338e4 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -6,7 +6,6 @@
#include "protocol.h"
#include "util.h"
#include "netbase.h"
-#include "main.h"
#ifndef WIN32
# include <arpa/inet.h>
@@ -22,7 +21,7 @@ static const char* ppszTypeName[] =
CMessageHeader::CMessageHeader()
{
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
+ memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
memset(pchCommand, 0, sizeof(pchCommand));
pchCommand[1] = 1;
nMessageSize = -1;
@@ -31,7 +30,7 @@ CMessageHeader::CMessageHeader()
CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
+ memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn;
nChecksum = 0;
@@ -48,7 +47,7 @@ std::string CMessageHeader::GetCommand() const
bool CMessageHeader::IsValid() const
{
// Check start string
- if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
+ if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
return false;
// Check the command string for errors
diff --git a/src/protocol.h b/src/protocol.h
index 4998425070..ae541dfdba 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -10,20 +10,12 @@
#ifndef __INCLUDED_PROTOCOL_H__
#define __INCLUDED_PROTOCOL_H__
+#include "chainparams.h"
#include "serialize.h"
#include "netbase.h"
#include <string>
#include "uint256.h"
-extern bool fTestNet;
-static inline unsigned short GetDefaultPort(const bool testnet = fTestNet)
-{
- return testnet ? 18333 : 8333;
-}
-
-
-extern unsigned char pchMessageStart[4];
-
/** Message header.
* (4) message start.
* (12) command.
@@ -50,7 +42,6 @@ class CMessageHeader
// TODO: make private (improves encapsulation)
public:
enum {
- MESSAGE_START_SIZE=sizeof(::pchMessageStart),
COMMAND_SIZE=12,
MESSAGE_SIZE_SIZE=sizeof(int),
CHECKSUM_SIZE=sizeof(int),
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 8529c88b39..8906174d7d 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -143,8 +143,13 @@ void AddressBookPage::setModel(AddressTableModel *model)
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
// Set column widths
+#if QT_VERSION < 0x050000
ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
+#else
+ ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
+ ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
+#endif
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged()));
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index f525d1bb38..76e88b36a7 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -17,16 +17,14 @@
#include "splashscreen.h"
#include <QMessageBox>
+#if QT_VERSION < 0x050000
#include <QTextCodec>
+#endif
#include <QLocale>
#include <QTimer>
#include <QTranslator>
#include <QLibraryInfo>
-#ifdef Q_OS_MAC
-#include "macdockiconhandler.h"
-#endif
-
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
@@ -115,12 +113,16 @@ static void handleRunawayException(std::exception *e)
#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
+ fHaveGUI = true;
+
// Command-line options take precedence:
ParseParameters(argc, argv);
+#if QT_VERSION < 0x050000
// Internal string conversion is all UTF-8
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
+#endif
Q_INIT_RESOURCE(bitcoin);
QApplication app(argc, argv);
@@ -152,7 +154,7 @@ int main(int argc, char *argv[])
// as it is used to locate QSettings)
QApplication::setOrganizationName("Bitcoin");
QApplication::setOrganizationDomain("bitcoin.org");
- if(GetBoolArg("-testnet")) // Separate UI settings for testnet
+ if (GetBoolArg("-testnet", false)) // Separate UI settings for testnet
QApplication::setApplicationName("Bitcoin-Qt-testnet");
else
QApplication::setApplicationName("Bitcoin-Qt");
@@ -202,15 +204,8 @@ int main(int argc, char *argv[])
return 1;
}
-#ifdef Q_OS_MAC
- // on mac, also change the icon now because it would look strange to have a testnet splash (green) and a std app icon (orange)
- if(GetBoolArg("-testnet")) {
- MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
- }
-#endif
-
SplashScreen splash(QPixmap(), 0);
- if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
+ if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
{
splash.show();
splash.setAutoFillBackground(true);
@@ -222,13 +217,16 @@ int main(int argc, char *argv[])
try
{
+#ifndef Q_OS_MAC
// Regenerate startup link, to fix links to old versions
+ // OSX: makes no sense on mac and might also scan/mount external (and sleeping) volumes (can take up some secs)
if (GUIUtil::GetStartOnSystemStartup())
GUIUtil::SetStartOnSystemStartup(true);
+#endif
boost::thread_group threadGroup;
- BitcoinGUI window;
+ BitcoinGUI window(GetBoolArg("-testnet", false), 0);
guiref = &window;
QTimer* pollShutdownTimer = new QTimer(guiref);
@@ -254,7 +252,7 @@ int main(int argc, char *argv[])
window.setCurrentWallet("~Default");
// If -min option passed, start window minimized.
- if(GetBoolArg("-min"))
+ if(GetBoolArg("-min", false))
{
window.showMinimized();
}
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index 0ec90a2946..c2f8308527 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -50,6 +50,7 @@
<file alias="update_spinner">res/movies/update_spinner.mng</file>
</qresource>
<qresource prefix="/translations">
+ <file alias="af_ZA">locale/bitcoin_af_ZA.qm</file>
<file alias="ar">locale/bitcoin_ar.qm</file>
<file alias="bg">locale/bitcoin_bg.qm</file>
<file alias="bs">locale/bitcoin_bs.ts</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 78a69af8b0..190da6caf8 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -44,7 +44,9 @@
#include <QMovie>
#include <QTimer>
#include <QDragEnterEvent>
+#if QT_VERSION < 0x050000
#include <QUrl>
+#endif
#include <QMimeData>
#include <QStyle>
#include <QSettings>
@@ -55,7 +57,7 @@
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
-BitcoinGUI::BitcoinGUI(QWidget *parent) :
+BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
QMainWindow(parent),
clientModel(0),
encryptWalletAction(0),
@@ -67,14 +69,30 @@ BitcoinGUI::BitcoinGUI(QWidget *parent) :
prevBlocks(0)
{
restoreWindowGeometry();
- setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
+
#ifndef Q_OS_MAC
- QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
- setWindowIcon(QIcon(":icons/bitcoin"));
+ if (!fIsTestnet)
+ {
+ setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
+ QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
+ setWindowIcon(QIcon(":icons/bitcoin"));
+ }
+ else
+ {
+ setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet") + " " + tr("[testnet]"));
+ QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+ setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+ }
#else
setUnifiedTitleAndToolBarOnMac(true);
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
+
+ if (!fIsTestnet)
+ MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin"));
+ else
+ MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
#endif
+
// Create wallet frame and make it the central widget
walletFrame = new WalletFrame(this);
setCentralWidget(walletFrame);
@@ -84,7 +102,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent) :
// Create actions for the toolbar, menu bar and tray/dock icon
// Needs walletFrame to be initialized
- createActions();
+ createActions(fIsTestnet);
// Create application menu bar
createMenuBar();
@@ -93,7 +111,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent) :
createToolBars();
// Create system tray icon and notification
- createTrayIcon();
+ createTrayIcon(fIsTestnet);
// Create status bar
statusBar();
@@ -157,7 +175,7 @@ BitcoinGUI::~BitcoinGUI()
#endif
}
-void BitcoinGUI::createActions()
+void BitcoinGUI::createActions(bool fIsTestnet)
{
QActionGroup *tabGroup = new QActionGroup(this);
@@ -211,7 +229,10 @@ void BitcoinGUI::createActions()
quitAction->setStatusTip(tr("Quit application"));
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
quitAction->setMenuRole(QAction::QuitRole);
- aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
+ if (!fIsTestnet)
+ aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
+ else
+ aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin"), this);
aboutAction->setStatusTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutRole);
aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
@@ -220,7 +241,10 @@ void BitcoinGUI::createActions()
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole);
- toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
+ if (!fIsTestnet)
+ toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
+ else
+ toggleHideAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&Show / Hide"), this);
toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
@@ -297,27 +321,6 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
this->clientModel = clientModel;
if(clientModel)
{
- // Replace some strings and icons, when using the testnet
- if(clientModel->isTestNet())
- {
- setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]"));
-#ifndef Q_OS_MAC
- QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
- setWindowIcon(QIcon(":icons/bitcoin_testnet"));
-#else
- MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
-#endif
- if(trayIcon)
- {
- // Just attach " [testnet]" to the existing tooltip
- trayIcon->setToolTip(trayIcon->toolTip() + QString(" ") + tr("[testnet]"));
- trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
- }
-
- toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet"));
- aboutAction->setIcon(QIcon(":/icons/toolbar_testnet"));
- }
-
// Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
// while the client has not yet fully loaded
createTrayIconMenu();
@@ -352,13 +355,22 @@ void BitcoinGUI::removeAllWallets()
walletFrame->removeAllWallets();
}
-void BitcoinGUI::createTrayIcon()
+void BitcoinGUI::createTrayIcon(bool fIsTestnet)
{
#ifndef Q_OS_MAC
trayIcon = new QSystemTrayIcon(this);
- trayIcon->setToolTip(tr("Bitcoin client"));
- trayIcon->setIcon(QIcon(":/icons/toolbar"));
+ if (!fIsTestnet)
+ {
+ trayIcon->setToolTip(tr("Bitcoin client"));
+ trayIcon->setIcon(QIcon(":/icons/toolbar"));
+ }
+ else
+ {
+ trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]"));
+ trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
+ }
+
trayIcon->show();
#endif
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index f361a62a41..685ce8b430 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -43,7 +43,7 @@ class BitcoinGUI : public QMainWindow
public:
static const QString DEFAULT_WALLET;
- explicit BitcoinGUI(QWidget *parent = 0);
+ explicit BitcoinGUI(bool fIsTestnet = false, QWidget *parent = 0);
~BitcoinGUI();
/** Set the client model.
@@ -113,13 +113,13 @@ private:
int prevBlocks;
/** Create the main UI actions. */
- void createActions();
+ void createActions(bool fIsTestnet);
/** Create the menu bar and sub-menus. */
void createMenuBar();
/** Create the toolbars */
void createToolBars();
/** Create system tray icon and notification */
- void createTrayIcon();
+ void createTrayIcon(bool fIsTestnet);
/** Create system tray menu (or setup the dock menu) */
void createTrayIconMenu();
/** Save window size and position */
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 4dae8999c3..1afce2eb7c 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -205,6 +205,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"),
-QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the databases using -reindex to change -txindex"),
+QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"),
}; \ No newline at end of file
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index e8d99a8d45..5cf4dd8111 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -5,6 +5,7 @@
#include "addresstablemodel.h"
#include "transactiontablemodel.h"
+#include "chainparams.h"
#include "alert.h"
#include "main.h"
#include "checkpoints.h"
@@ -110,7 +111,7 @@ void ClientModel::updateAlert(const QString &hash, int status)
bool ClientModel::isTestNet() const
{
- return fTestNet;
+ return TestNet();
}
bool ClientModel::inInitialBlockDownload() const
diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui
index 57aa624cc2..a4cf641195 100644
--- a/src/qt/forms/overviewpage.ui
+++ b/src/qt/forms/overviewpage.ui
@@ -103,7 +103,7 @@
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
- <string>Balance:</string>
+ <string>Confirmed:</string>
</property>
</widget>
</item>
@@ -119,7 +119,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
- <string>Your current balance</string>
+ <string>Your current spendable balance</string>
</property>
<property name="text">
<string notr="true">0 BTC</string>
@@ -148,7 +148,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
- <string>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</string>
+ <string>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</string>
</property>
<property name="text">
<string notr="true">0 BTC</string>
@@ -184,6 +184,42 @@
</property>
</widget>
</item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="labelTotalText">
+ <property name="text">
+ <string>Total:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="labelTotal">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Your current total balance</string>
+ </property>
+ <property name="text">
+ <string notr="true">0 BTC</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
</layout>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 2105f0730e..88a6e7226e 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -13,8 +13,12 @@
#include <QDoubleValidator>
#include <QFont>
#include <QLineEdit>
+#if QT_VERSION >= 0x050000
+#include <QUrlQuery>
+#else
#include <QUrl>
-#include <QTextDocument> // For Qt::escape
+#endif
+#include <QTextDocument> // for Qt::mightBeRichText
#include <QAbstractItemView>
#include <QClipboard>
#include <QFileDialog>
@@ -86,7 +90,13 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
SendCoinsRecipient rv;
rv.address = uri.path();
rv.amount = 0;
+
+#if QT_VERSION < 0x050000
QList<QPair<QString, QString> > items = uri.queryItems();
+#else
+ QUrlQuery uriQuery(uri);
+ QList<QPair<QString, QString> > items = uriQuery.queryItems();
+#endif
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -139,7 +149,11 @@ bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
QString HtmlEscape(const QString& str, bool fMultiLine)
{
+#if QT_VERSION < 0x050000
QString escaped = Qt::escape(str);
+#else
+ QString escaped = str.toHtmlEscaped();
+#endif
if(fMultiLine)
{
escaped = escaped.replace("\n", "<br>\n");
@@ -176,7 +190,11 @@ QString getSaveFileName(QWidget *parent, const QString &caption,
QString myDir;
if(dir.isEmpty()) // Default to user documents location
{
+#if QT_VERSION < 0x050000
myDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+#else
+ myDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+#endif
}
else
{
@@ -408,10 +426,61 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
return true;
}
-#else
-// TODO: OSX startup stuff; see:
-// https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
+
+#elif defined(Q_OS_MAC)
+// based on: https://github.com/Mozketo/LaunchAtLoginController/blob/master/LaunchAtLoginController.m
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+
+LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl);
+LSSharedFileListItemRef findStartupItemInList(LSSharedFileListRef list, CFURLRef findUrl)
+{
+ // loop through the list of startup items and try to find the bitcoin app
+ CFArrayRef listSnapshot = LSSharedFileListCopySnapshot(list, NULL);
+ for(int i = 0; i < CFArrayGetCount(listSnapshot); i++) {
+ LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(listSnapshot, i);
+ UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
+ CFURLRef currentItemURL = NULL;
+ LSSharedFileListItemResolve(item, resolutionFlags, &currentItemURL, NULL);
+ if(currentItemURL && CFEqual(currentItemURL, findUrl)) {
+ // found
+ CFRelease(currentItemURL);
+ return item;
+ }
+ if(currentItemURL) {
+ CFRelease(currentItemURL);
+ }
+ }
+ return NULL;
+}
+
+bool GetStartOnSystemStartup()
+{
+ CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+ LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
+ LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
+ return !!foundItem; // return boolified object
+}
+
+bool SetStartOnSystemStartup(bool fAutoStart)
+{
+ CFURLRef bitcoinAppUrl = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+ LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
+ LSSharedFileListItemRef foundItem = findStartupItemInList(loginItems, bitcoinAppUrl);
+
+ if(fAutoStart && !foundItem) {
+ // add bitcoin app to startup item list
+ LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, NULL, NULL, bitcoinAppUrl, NULL, NULL);
+ }
+ else if(!fAutoStart && foundItem) {
+ // remove item
+ LSSharedFileListItemRemove(loginItems, foundItem);
+ }
+ return true;
+}
+#else
bool GetStartOnSystemStartup() { return false; }
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts
new file mode 100644
index 0000000000..029b91a7a0
--- /dev/null
+++ b/src/qt/locale/bitcoin_af_ZA.ts
@@ -0,0 +1,2917 @@
+<?xml version="1.0" ?><!DOCTYPE TS><TS language="af_ZA" version="2.0">
+<defaultcodec>UTF-8</defaultcodec>
+<context>
+ <name>AboutDialog</name>
+ <message>
+ <location filename="../forms/aboutdialog.ui" line="+14"/>
+ <source>About Bitcoin</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+39"/>
+ <source>&lt;b&gt;Bitcoin&lt;/b&gt; version</source>
+ <translation>&lt;b&gt;Bitcoin&lt;/b&gt; weergawe</translation>
+ </message>
+ <message>
+ <location line="+57"/>
+ <source>
+This is experimental software.
+
+Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../aboutdialog.cpp" line="+14"/>
+ <source>Copyright</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The Bitcoin developers</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <location filename="../forms/addressbookpage.ui" line="+14"/>
+ <source>Address Book</source>
+ <translation>Adres Boek</translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Double-click to edit address or label</source>
+ <translation>Dubbel-klik om die adres of etiket te wysig</translation>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Create a new address</source>
+ <translation>Skep &apos;n nuwe adres</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Maak &apos;n kopie van die huidige adres na die stelsel klipbord</translation>
+ </message>
+ <message>
+ <location line="-11"/>
+ <source>&amp;New Address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../addressbookpage.cpp" line="+63"/>
+ <source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../forms/addressbookpage.ui" line="+14"/>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Show &amp;QR Code</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Sign a message to prove you own a Bitcoin address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Sign &amp;Message</source>
+ <translation>Teken &amp;Boodskap</translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Export</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-44"/>
+ <source>Verify a message to ensure it was signed with a specified Bitcoin address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>&amp;Delete</source>
+ <translation>&amp;Verwyder</translation>
+ </message>
+ <message>
+ <location filename="../addressbookpage.cpp" line="-5"/>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>&amp;Edit</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Send &amp;Coins</source>
+ <translation>Stuur &amp;Muntstukke</translation>
+ </message>
+ <message>
+ <location line="+260"/>
+ <source>Export Address Book Data</source>
+ <translation>Voer die Adresboek Data Uit</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Comma separated file (*.csv)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Error exporting</source>
+ <translation>Fout uitvoering</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Could not write to file %1.</source>
+ <translation>Kon nie na die %1 lêer skryf nie</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <location filename="../addresstablemodel.cpp" line="+144"/>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Address</source>
+ <translation>Adres</translation>
+ </message>
+ <message>
+ <location line="+36"/>
+ <source>(no label)</source>
+ <translation>(geen etiket)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <location filename="../forms/askpassphrasedialog.ui" line="+26"/>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>Enter passphrase</source>
+ <translation>Tik Wagwoord in</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>New passphrase</source>
+ <translation>Nuwe wagwoord</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Repeat new passphrase</source>
+ <translation>Herhaal nuwe wagwoord</translation>
+ </message>
+ <message>
+ <location filename="../askpassphrasedialog.cpp" line="+33"/>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation>Tik die nuwe wagwoord vir die beursie in.&lt;br/&gt;Gebruik asseblief &apos;n wagwoord van &lt;b&gt;ten minste 10 ewekansige karakters&lt;/b&gt;, of &lt;b&gt;agt (8) of meer woorde.&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Encrypt wallet</source>
+ <translation>Enkripteer beursie</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Hierdie operasie benodig &apos;n wagwoord om die beursie oop te sluit.</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Unlock wallet</source>
+ <translation>Sluit beursie oop</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>Hierdie operasie benodig &apos;n wagwoord om die beursie oop te sluit.</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Decrypt wallet</source>
+ <translation>Sluit beursie oop</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Change passphrase</source>
+ <translation>Verander wagwoord</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Enter the old and new passphrase to the wallet.</source>
+ <translation>Tik asseblief die ou en nuwe wagwoord vir die beursie in.</translation>
+ </message>
+ <message>
+ <location line="+46"/>
+ <source>Confirm wallet encryption</source>
+ <translation>Bevestig beursie enkripsie.</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+100"/>
+ <location line="+24"/>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-130"/>
+ <location line="+58"/>
+ <source>Wallet encrypted</source>
+ <translation>Die beursie is nou bewaak</translation>
+ </message>
+ <message>
+ <location line="-56"/>
+ <source>Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <location line="+7"/>
+ <location line="+42"/>
+ <location line="+6"/>
+ <source>Wallet encryption failed</source>
+ <translation>Die beursie kon nie bewaak word nie</translation>
+ </message>
+ <message>
+ <location line="-54"/>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation>Beursie bewaaking het misluk as gevolg van &apos;n interne fout. Die beursie is nie bewaak nie!</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <location line="+48"/>
+ <source>The supplied passphrases do not match.</source>
+ <translation>Die wagwoord stem nie ooreen nie</translation>
+ </message>
+ <message>
+ <location line="-37"/>
+ <source>Wallet unlock failed</source>
+ <translation>Beursie oopsluiting het misluk</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <location line="+11"/>
+ <location line="+19"/>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation>Die wagwoord wat ingetik was om die beursie oop te sluit, was verkeerd.</translation>
+ </message>
+ <message>
+ <location line="-20"/>
+ <source>Wallet decryption failed</source>
+ <translation>Beursie dekripsie het misluk</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <location filename="../bitcoingui.cpp" line="+233"/>
+ <source>Sign &amp;message...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+280"/>
+ <source>Synchronizing with network...</source>
+ <translation>Sinchroniseer met die netwerk ...</translation>
+ </message>
+ <message>
+ <location line="-349"/>
+ <source>&amp;Overview</source>
+ <translation>&amp;Oorsig</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show general overview of wallet</source>
+ <translation>Wys algemene oorsig van die beursie</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transaksies</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Browse transaction history</source>
+ <translation>Besoek transaksie geskiedenis</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Edit the list of stored addresses and labels</source>
+ <translation>Wysig die lys van gestoorde adresse en etikette</translation>
+ </message>
+ <message>
+ <location line="-14"/>
+ <source>Show the list of addresses for receiving payments</source>
+ <translation>Wys die lys van adresse vir die ontvangs van betalings</translation>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>E&amp;xit</source>
+ <translation>S&amp;luit af</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Quit application</source>
+ <translation>Sluit af</translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Show information about Bitcoin</source>
+ <translation>Wys inligting oor Bitcoin</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>About &amp;Qt</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show information about Qt</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>&amp;Options...</source>
+ <translation>&amp;Opsies</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Backup Wallet...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>&amp;Change Passphrase...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+285"/>
+ <source>Importing blocks from disk...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Reindexing blocks on disk...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-347"/>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+49"/>
+ <source>Modify configuration options for Bitcoin</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Debug window</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Open debugging and diagnostic console</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-4"/>
+ <source>&amp;Verify message...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-165"/>
+ <location line="+530"/>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <location line="-530"/>
+ <source>Wallet</source>
+ <translation>Beursie</translation>
+ </message>
+ <message>
+ <location line="+101"/>
+ <source>&amp;Send</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Receive</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>&amp;Addresses</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>&amp;About Bitcoin</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>&amp;Show / Hide</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show or hide the main Window</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+28"/>
+ <source>&amp;File</source>
+ <translation>&amp;Lêer</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Settings</source>
+ <translation>&amp;Instellings</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Help</source>
+ <translation>&amp;Hulp</translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Tabs toolbar</source>
+ <translation>Blad nutsbalk</translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <location line="+10"/>
+ <source>[testnet]</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+47"/>
+ <source>Bitcoin client</source>
+ <translation type="unfinished"/>
+ </message>
+ <message numerus="yes">
+ <location line="+141"/>
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>No block source available...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Processed %1 of %2 (estimated) blocks of transaction history.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Processed %1 blocks of transaction history.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message numerus="yes">
+ <location line="+20"/>
+ <source>%n hour(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <location line="+4"/>
+ <source>%n day(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <location line="+4"/>
+ <source>%n week(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>%1 behind</source>
+ <translation>%1 agter</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Ontvangs van laaste blok is %1 terug.</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Warning</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Information</source>
+ <translation>Informasie</translation>
+ </message>
+ <message>
+ <location line="+70"/>
+ <source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-140"/>
+ <source>Up to date</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Catching up...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+113"/>
+ <source>Confirm transaction fee</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Sent transaction</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Incoming transaction</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Date: %1
+Amount: %2
+Type: %3
+Address: %4
+</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+33"/>
+ <location line="+23"/>
+ <source>URI handling</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-23"/>
+ <location line="+23"/>
+ <source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../bitcoin.cpp" line="+111"/>
+ <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>ClientModel</name>
+ <message>
+ <location filename="../clientmodel.cpp" line="+104"/>
+ <source>Network Alert</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <location filename="../forms/editaddressdialog.ui" line="+14"/>
+ <source>Edit Address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>&amp;Label</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>The label associated with this address book entry</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>The address associated with this address book entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../editaddressdialog.cpp" line="+21"/>
+ <source>New receiving address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>New sending address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Edit receiving address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Edit sending address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+76"/>
+ <source>The entered address &quot;%1&quot; is already in the address book.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-5"/>
+ <source>The entered address &quot;%1&quot; is not a valid Bitcoin address.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>New key generation failed.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>GUIUtil::HelpMessageBox</name>
+ <message>
+ <location filename="../guiutil.cpp" line="+424"/>
+ <location line="+12"/>
+ <source>Bitcoin-Qt</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-12"/>
+ <source>version</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Usage:</source>
+ <translation>Gebruik:</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>command-line options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>UI options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Set language, for example &quot;de_DE&quot; (default: system locale)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Start minimized</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show splash screen on startup (default: 1)</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <location filename="../forms/optionsdialog.ui" line="+14"/>
+ <source>Options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>&amp;Main</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Pay transaction &amp;fee</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Automatically start Bitcoin after logging in to the system.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Start Bitcoin on system login</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+35"/>
+ <source>Reset all client options to default.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Reset Options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>&amp;Network</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Map port using &amp;UPnP</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Connect through SOCKS proxy:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Proxy &amp;IP:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>IP address of the proxy (e.g. 127.0.0.1)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Port:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>SOCKS &amp;Version:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>SOCKS version of the proxy (e.g. 5)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+36"/>
+ <source>&amp;Window</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>M&amp;inimize on close</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>&amp;Display</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>User Interface &amp;language:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>The user interface language can be set here. This setting will take effect after restarting Bitcoin.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Whether to show Bitcoin addresses in the transaction list or not.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Display addresses in transaction list</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+71"/>
+ <source>&amp;OK</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Cancel</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>&amp;Apply</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../optionsdialog.cpp" line="+53"/>
+ <source>default</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+130"/>
+ <source>Confirm options reset</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Some settings may require a client restart to take effect.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Do you want to proceed?</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+42"/>
+ <location line="+9"/>
+ <source>Warning</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-9"/>
+ <location line="+9"/>
+ <source>This setting will take effect after restarting Bitcoin.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>The supplied proxy address is invalid.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <location filename="../forms/overviewpage.ui" line="+14"/>
+ <source>Form</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+50"/>
+ <location line="+166"/>
+ <source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-124"/>
+ <source>Balance:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Unconfirmed:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-78"/>
+ <source>Wallet</source>
+ <translation>Beursie</translation>
+ </message>
+ <message>
+ <location line="+107"/>
+ <source>Immature:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Mined balance that has not yet matured</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+46"/>
+ <source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-101"/>
+ <source>Your current balance</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../overviewpage.cpp" line="+116"/>
+ <location line="+1"/>
+ <source>out of sync</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <location filename="../paymentserver.cpp" line="+107"/>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>QRCodeDialog</name>
+ <message>
+ <location filename="../forms/qrcodedialog.ui" line="+14"/>
+ <source>QR Code Dialog</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+59"/>
+ <source>Request Payment</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+56"/>
+ <source>Amount:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-44"/>
+ <source>Label:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Message:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+71"/>
+ <source>&amp;Save As...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../qrcodedialog.cpp" line="+62"/>
+ <source>Error encoding URI into QR Code.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+40"/>
+ <source>The entered amount is invalid, please check.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Save QR Code</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>PNG Images (*.png)</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <location filename="../forms/rpcconsole.ui" line="+46"/>
+ <source>Client name</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <location line="+23"/>
+ <location line="+26"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+36"/>
+ <location line="+53"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location filename="../rpcconsole.cpp" line="+339"/>
+ <source>N/A</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-217"/>
+ <source>Client version</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-45"/>
+ <source>&amp;Information</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+68"/>
+ <source>Using OpenSSL version</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+49"/>
+ <source>Startup time</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Network</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Number of connections</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>On testnet</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Block chain</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Current number of blocks</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Estimated total blocks</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Last block time</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+52"/>
+ <source>&amp;Open</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Command-line options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>&amp;Show</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+24"/>
+ <source>&amp;Console</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-260"/>
+ <source>Build date</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-104"/>
+ <source>Bitcoin - Debug window</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Bitcoin Core</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+279"/>
+ <source>Debug log file</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+102"/>
+ <source>Clear console</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../rpcconsole.cpp" line="-30"/>
+ <source>Welcome to the Bitcoin RPC console.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Use up and down arrows to navigate history, and &lt;b&gt;Ctrl-L&lt;/b&gt; to clear screen.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Type &lt;b&gt;help&lt;/b&gt; for an overview of available commands.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <location filename="../forms/sendcoinsdialog.ui" line="+14"/>
+ <location filename="../sendcoinsdialog.cpp" line="+124"/>
+ <location line="+5"/>
+ <location line="+5"/>
+ <location line="+5"/>
+ <location line="+6"/>
+ <location line="+5"/>
+ <location line="+5"/>
+ <source>Send Coins</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+50"/>
+ <source>Send to multiple recipients at once</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Add &amp;Recipient</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>Remove all transaction fields</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Balance:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>123.456 BTC</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Confirm the send action</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>S&amp;end</source>
+ <translation>S&amp;tuur</translation>
+ </message>
+ <message>
+ <location filename="../sendcoinsdialog.cpp" line="-59"/>
+ <source>&lt;b&gt;%1&lt;/b&gt; to %2 (%3)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Confirm send coins</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Are you sure you want to send %1?</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source> and </source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>The recipient address is not valid, please recheck.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>The amount exceeds your balance.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Duplicate address found, can only send to each address once per send operation.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Error: Transaction creation failed!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>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.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <location filename="../forms/sendcoinsentry.ui" line="+14"/>
+ <source>Form</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>A&amp;mount:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Pay &amp;To:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation>Die adres waarheen die betaling gestuur moet word (b.v. 1H7wyVL5HCNoVFyyBJSDojwyxcCChU7TPA)</translation>
+ </message>
+ <message>
+ <location line="+60"/>
+ <location filename="../sendcoinsentry.cpp" line="+26"/>
+ <source>Enter a label for this address to add it to your address book</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-78"/>
+ <source>&amp;Label:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+28"/>
+ <source>Choose address from address book</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Alt+A</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Alt+P</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Remove this recipient</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../sendcoinsentry.cpp" line="+1"/>
+ <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <location filename="../forms/signverifymessagedialog.ui" line="+14"/>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Teken boodskap</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <location line="+213"/>
+ <source>Choose an address from the address book</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-203"/>
+ <location line="+213"/>
+ <source>Alt+A</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-203"/>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Alt+P</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Enter the message you want to sign here</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Signature</source>
+ <translation>Handtekening</translation>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Sign &amp;Message</source>
+ <translation>Teken &amp;Boodskap</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Reset all sign message fields</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <location line="+146"/>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-87"/>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+40"/>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Verify &amp;Message</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Reset all verify message fields</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../signverifymessagedialog.cpp" line="+27"/>
+ <location line="+3"/>
+ <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-2"/>
+ <source>Click &quot;Sign Message&quot; to generate signature</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Enter Bitcoin signature</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+82"/>
+ <location line="+81"/>
+ <source>The entered address is invalid.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-81"/>
+ <location line="+8"/>
+ <location line="+73"/>
+ <location line="+8"/>
+ <source>Please check the address and try again.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-81"/>
+ <location line="+81"/>
+ <source>The entered address does not refer to a key.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-73"/>
+ <source>Wallet unlock was cancelled.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Private key for the entered address is not available.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Message signing failed.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Message signed.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+59"/>
+ <source>The signature could not be decoded.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <location line="+13"/>
+ <source>Please check the signature and try again.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The signature did not match the message digest.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Message verification failed.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Message verified.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>SplashScreen</name>
+ <message>
+ <location filename="../splashscreen.cpp" line="+22"/>
+ <source>The Bitcoin developers</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>[testnet]</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <location filename="../transactiondesc.cpp" line="+20"/>
+ <source>Open until %1</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>%1/offline</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>%1/unconfirmed</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>%1 confirmations</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Status</source>
+ <translation type="unfinished"/>
+ </message>
+ <message numerus="yes">
+ <location line="+7"/>
+ <source>, broadcast through %n node(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Source</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Generated</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <location line="+17"/>
+ <source>From</source>
+ <translation>Van</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <location line="+22"/>
+ <location line="+58"/>
+ <source>To</source>
+ <translation>Na</translation>
+ </message>
+ <message>
+ <location line="-77"/>
+ <location line="+2"/>
+ <source>own address</source>
+ <translation>eie adres</translation>
+ </message>
+ <message>
+ <location line="-2"/>
+ <source>label</source>
+ <translation>etiket</translation>
+ </message>
+ <message>
+ <location line="+37"/>
+ <location line="+12"/>
+ <location line="+45"/>
+ <location line="+17"/>
+ <location line="+30"/>
+ <source>Credit</source>
+ <translation>Krediet</translation>
+ </message>
+ <message numerus="yes">
+ <location line="-102"/>
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>not accepted</source>
+ <translation>nie aanvaar nie</translation>
+ </message>
+ <message>
+ <location line="+44"/>
+ <location line="+8"/>
+ <location line="+15"/>
+ <location line="+30"/>
+ <source>Debit</source>
+ <translation>Debiet</translation>
+ </message>
+ <message>
+ <location line="-39"/>
+ <source>Transaction fee</source>
+ <translation>Transaksie fooi</translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Net amount</source>
+ <translation>Netto bedrag</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Message</source>
+ <translation>Boodskap</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Comment</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Transaction ID</source>
+ <translation>Transaksie ID</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Debug information</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Transaction</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Inputs</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>true</source>
+ <translation>waar</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>false</source>
+ <translation>onwaar</translation>
+ </message>
+ <message>
+ <location line="-209"/>
+ <source>, has not been successfully broadcast yet</source>
+ <translation type="unfinished"/>
+ </message>
+ <message numerus="yes">
+ <location line="-35"/>
+ <source>Open for %n more block(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+70"/>
+ <source>unknown</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>TransactionDescDialog</name>
+ <message>
+ <location filename="../forms/transactiondescdialog.ui" line="+14"/>
+ <source>Transaction details</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <location filename="../transactiontablemodel.cpp" line="+225"/>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Address</source>
+ <translation>Adres</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message numerus="yes">
+ <location line="+57"/>
+ <source>Open for %n more block(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Open until %1</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Offline (%1 confirmations)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Unconfirmed (%1 of %2 confirmations)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message numerus="yes">
+ <location line="+8"/>
+ <source>Mined balance will be available when it matures in %n more block(s)</source>
+ <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>This block was not received by any other nodes and will probably not be accepted!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Generated but not accepted</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+43"/>
+ <source>Received with</source>
+ <translation>Ontvang met</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Received from</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Sent to</source>
+ <translation>Gestuur na</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Payment to yourself</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Mined</source>
+ <translation>Gemyn</translation>
+ </message>
+ <message>
+ <location line="+38"/>
+ <source>(n/a)</source>
+ <translation>(n.v.t)</translation>
+ </message>
+ <message>
+ <location line="+199"/>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Datum en tyd wat die transaksie ontvang was.</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Type of transaction.</source>
+ <translation>Tipe transaksie.</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Destination address of transaction.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Amount removed from or added to balance.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <location filename="../transactionview.cpp" line="+52"/>
+ <location line="+16"/>
+ <source>All</source>
+ <translation>Alles</translation>
+ </message>
+ <message>
+ <location line="-15"/>
+ <source>Today</source>
+ <translation>Vandag</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This week</source>
+ <translation>Hierdie week</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This month</source>
+ <translation>Hierdie maand</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Last month</source>
+ <translation>Verlede maand</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This year</source>
+ <translation>Hierdie jaar</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Range...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Received with</source>
+ <translation>Ontvang met</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Sent to</source>
+ <translation>Gestuur na</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>To yourself</source>
+ <translation>Aan/na jouself</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Mined</source>
+ <translation>Gemyn</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Other</source>
+ <translation>Ander</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Min amount</source>
+ <translation>Min bedrag</translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Copy address</source>
+ <translation>Maak kopie van adres</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy label</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy amount</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy transaction ID</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Edit label</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show transaction details</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+139"/>
+ <source>Export Transaction Data</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Comma separated file (*.csv)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Confirmed</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Date</source>
+ <translation>Datum</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Type</source>
+ <translation>Tipe</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Address</source>
+ <translation>Adres</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Amount</source>
+ <translation>Bedrag</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Error exporting</source>
+ <translation>Fout uitvoering</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Could not write to file %1.</source>
+ <translation>Kon nie na die %1 lêer skryf nie</translation>
+ </message>
+ <message>
+ <location line="+100"/>
+ <source>Range:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>to</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <location filename="../walletmodel.cpp" line="+193"/>
+ <source>Send Coins</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <location filename="../walletview.cpp" line="+42"/>
+ <source>&amp;Export</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+193"/>
+ <source>Backup Wallet</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Wallet Data (*.dat)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Backup Failed</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>There was an error trying to save the wallet data to the new location.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Backup Successful</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The wallet data was successfully saved to the new location.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <location filename="../bitcoinstrings.cpp" line="+94"/>
+ <source>Bitcoin version</source>
+ <translation>Bitcoin weergawe</translation>
+ </message>
+ <message>
+ <location line="+102"/>
+ <source>Usage:</source>
+ <translation>Gebruik:</translation>
+ </message>
+ <message>
+ <location line="-29"/>
+ <source>Send command to -server or bitcoind</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-23"/>
+ <source>List commands</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-12"/>
+ <source>Get help for a command</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+24"/>
+ <source>Options:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+24"/>
+ <source>Specify configuration file (default: bitcoin.conf)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Specify pid file (default: bitcoind.pid)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-1"/>
+ <source>Specify data directory</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-9"/>
+ <source>Set database cache size in megabytes (default: 25)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-28"/>
+ <source>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Maintain at most &lt;n&gt; connections to peers (default: 125)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-48"/>
+ <source>Connect to a node to retrieve peer addresses, and disconnect</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+82"/>
+ <source>Specify your own public address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Threshold for disconnecting misbehaving peers (default: 100)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-134"/>
+ <source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-29"/>
+ <source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+37"/>
+ <source>Accept command line and JSON-RPC commands</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+76"/>
+ <source>Run in the background as a daemon and accept commands</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+37"/>
+ <source>Use the test network</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-112"/>
+ <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-80"/>
+ <source>%s, you must set a rpcpassword in the configuration file:
+%s
+It is recommended you use the following random password:
+rpcuser=bitcoinrpc
+rpcpassword=%s
+(you do not need to remember this password)
+The username and password MUST NOT be the same.
+If the file does not exist, create it with owner-readable-only file permissions.
+It is also recommended to set alertnotify so you are notified of problems;
+for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
+</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Cannot obtain a lock on data directory %s. Bitcoin is probably already running.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>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.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Execute command when a relevant alert is received (%s in cmd is replaced by message)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Warning: Please check that your computer&apos;s date and time are correct! If your clock is wrong Bitcoin will not work properly.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Attempt to recover private keys from a corrupt wallet.dat</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Block creation options:</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Connect only to the specified node(s)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Corrupted block database detected</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Discover own IP address (default: 1 when listening and no -externalip)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Error initializing block database</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error loading block database</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Error opening block database</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Error: Disk space is low!</source>
+ <translation>Fout: Hardeskyf spasie is baie laag!</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Wallet locked, unable to create transaction!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: system error: </source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to read block info</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to read block</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to sync block index</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write block index</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write block info</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write block</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write file info</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write to coin database</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write transaction index</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Failed to write undo data</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Find peers using DNS lookup (default: 1 unless -connect)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Generate coins (default: 0)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>How many blocks to check at startup (default: 288, 0 = all)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>How thorough the block verification is (0-4, default: 3)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Not enough file descriptors available.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Rebuild block chain index from current blk000??.dat files</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Set the number of threads to service RPC calls (default: 4)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>Verifying blocks...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Verifying wallet...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-69"/>
+ <source>Imports blocks from external blk000??.dat file</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-76"/>
+ <source>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+77"/>
+ <source>Information</source>
+ <translation>Informasie</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Invalid -tor address: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Maintain a full transaction index (default: 0)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: 5000)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: 1000)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Only accept block chain matching built-in checkpoints (default: 1)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Only connect to nodes in network &lt;net&gt; (IPv4, IPv6 or Tor)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Output extra debugging information. Implies all other -debug* options</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Output extra network debugging information</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Prepend debug output with timestamp</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Select the version of socks proxy to use (4-5, default: 5)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Send trace/debug info to console instead of debug.log file</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Send trace/debug info to debugger</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Set maximum block size in bytes (default: 250000)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Set minimum block size in bytes (default: 0)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Signing transaction failed</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Specify connection timeout in milliseconds (default: 5000)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>System error: </source>
+ <translation>Sisteem fout:</translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Transaction amount too small</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Transaction amounts must be positive</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Transaction too large</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Use UPnP to map the listening port (default: 0)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Use UPnP to map the listening port (default: 1 when listening)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Use proxy to reach tor hidden services (default: same as -proxy)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Username for JSON-RPC connections</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Warning</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Warning: This version is obsolete, upgrade required!</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>You need to rebuild the databases using -reindex to change -txindex</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>wallet.dat corrupt, salvage failed</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-50"/>
+ <source>Password for JSON-RPC connections</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-67"/>
+ <source>Allow JSON-RPC connections from specified IP address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+76"/>
+ <source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-120"/>
+ <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+147"/>
+ <source>Upgrade wallet to latest format</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-21"/>
+ <source>Set key pool size to &lt;n&gt; (default: 100)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-12"/>
+ <source>Rescan the block chain for missing wallet transactions</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+35"/>
+ <source>Use OpenSSL (https) for JSON-RPC connections</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-26"/>
+ <source>Server certificate file (default: server.cert)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Server private key (default: server.pem)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-151"/>
+ <source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+165"/>
+ <source>This help message</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Unable to bind to %s on this computer (bind returned error %d, %s)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-91"/>
+ <source>Connect through socks proxy</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-10"/>
+ <source>Allow DNS lookups for -addnode, -seednode and -connect</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+55"/>
+ <source>Loading addresses...</source>
+ <translation>Laai adresse...</translation>
+ </message>
+ <message>
+ <location line="-35"/>
+ <source>Error loading wallet.dat: Wallet corrupted</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error loading wallet.dat: Wallet requires newer version of Bitcoin</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+93"/>
+ <source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-95"/>
+ <source>Error loading wallet.dat</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+28"/>
+ <source>Invalid -proxy address: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+56"/>
+ <source>Unknown network specified in -onlynet: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-1"/>
+ <source>Unknown -socks proxy version requested: %i</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-96"/>
+ <source>Cannot resolve -bind address: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Cannot resolve -externalip address: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+44"/>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Invalid amount</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-6"/>
+ <source>Insufficient funds</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Loading block index...</source>
+ <translation>Laai blok indeks...</translation>
+ </message>
+ <message>
+ <location line="-57"/>
+ <source>Add a node to connect to and attempt to keep the connection open</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-25"/>
+ <source>Unable to bind to %s on this computer. Bitcoin is probably already running.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+64"/>
+ <source>Fee per KB to add to transactions you send</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Loading wallet...</source>
+ <translation>Laai beursie...</translation>
+ </message>
+ <message>
+ <location line="-52"/>
+ <source>Cannot downgrade wallet</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Cannot write default address</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="+64"/>
+ <source>Rescanning...</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-57"/>
+ <source>Done loading</source>
+ <translation>Klaar gelaai</translation>
+ </message>
+ <message>
+ <location line="+82"/>
+ <source>To use the %s option</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location line="-74"/>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ <message>
+ <location line="-31"/>
+ <source>You must set rpcpassword=&lt;password&gt; in the configuration file:
+%s
+If the file does not exist, create it with owner-readable-only file permissions.</source>
+ <translation type="unfinished"/>
+ </message>
+</context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 028080d545..741a25a4da 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -38,7 +38,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location filename="../forms/addressbookpage.ui" line="+14"/>
<source>Address Book</source>
- <translation>كتاب العنوانين</translation>
+ <translation>دفتر العناوين</translation>
</message>
<message>
<location line="+19"/>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index 5d857ee6f6..ac9db97fe7 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -2722,7 +2722,7 @@ zum Beispiel: alertnotify=echo %%s | mail -s \&quot;Bitcoin Alert\&quot; admin@f
<message>
<location line="+1"/>
<source>You need to rebuild the databases using -reindex to change -txindex</source>
- <translation>Sie müssen die Datenbanken mit Hilfe von -reindex neu aufbauen, um -txindex verändern zu können.</translation>
+ <translation>Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um -txindex zu verändern.</translation>
</message>
<message>
<location line="+1"/>
diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts
index 9d197f58ed..22125e2bb7 100644
--- a/src/qt/locale/bitcoin_el_GR.ts
+++ b/src/qt/locale/bitcoin_el_GR.ts
@@ -20,17 +20,22 @@ This is experimental software.
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</source>
- <translation type="unfinished"/>
+ <translation>
+This is experimental software.
+
+Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</translation>
</message>
<message>
<location filename="../aboutdialog.cpp" line="+14"/>
<source>Copyright</source>
- <translation type="unfinished"/>
+ <translation>Πνευματική ιδιοκτησία </translation>
</message>
<message>
<location line="+0"/>
<source>The Bitcoin developers</source>
- <translation type="unfinished"/>
+ <translation>Οι Bitcoin προγραμματιστές </translation>
</message>
</context>
<context>
@@ -88,7 +93,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+25"/>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος</translation>
</message>
<message>
<location line="+27"/>
@@ -98,7 +103,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+3"/>
<source>&amp;Export</source>
- <translation type="unfinished"/>
+ <translation>&amp;Εξαγωγή</translation>
</message>
<message>
<location line="-44"/>
@@ -118,7 +123,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location filename="../addressbookpage.cpp" line="-5"/>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished"/>
+ <translation>Αυτές είναι οι Bitcoin διευθύνσεις σας για να λαμβάνετε πληρωμές. Δίνοντας μία ξεχωριστή διεύθυνση σε κάθε αποστολέα, θα μπορείτε να ελέγχετε ποιος σας πληρώνει.</translation>
</message>
<message>
<location line="+13"/>
@@ -133,7 +138,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>Send &amp;Coins</source>
- <translation type="unfinished"/>
+ <translation>Αποστολή νομισμάτων</translation>
</message>
<message>
<location line="+260"/>
@@ -179,7 +184,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location filename="../forms/askpassphrasedialog.ui" line="+26"/>
<source>Passphrase Dialog</source>
- <translation type="unfinished"/>
+ <translation>Φράση πρόσβασης </translation>
</message>
<message>
<location line="+21"/>
@@ -244,23 +249,24 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished"/>
+ <translation>Προσοχη: Εαν κρυπτογραφησεις το πορτοφολι σου και χάσεις τον κωδικο σου θα χάσεις &lt;b&gt; ΟΛΑ ΣΟΥ ΤΑ BITCOINS&lt;/b&gt;!
+Είσαι σίγουρος ότι θέλεις να κρυπτογραφησεις το πορτοφολι;</translation>
</message>
<message>
<location line="+0"/>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished"/>
+ <translation>Είστε σίγουροι ότι θέλετε να κρυπτογραφήσετε το πορτοφόλι σας;</translation>
</message>
<message>
<location line="+15"/>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished"/>
+ <translation>ΣΗΜΑΝΤΙΚΟ: Τα προηγούμενα αντίγραφα ασφαλείας που έχετε κάνει από το αρχείο του πορτοφόλιου σας θα πρέπει να αντικατασταθουν με το νέο που δημιουργείται, κρυπτογραφημένο αρχείο πορτοφόλιου. Για λόγους ασφαλείας, τα προηγούμενα αντίγραφα ασφαλείας του μη κρυπτογραφημένου αρχείου πορτοφόλιου θα καταστουν άχρηστα μόλις αρχίσετε να χρησιμοποιείτε το νέο κρυπτογραφημένο πορτοφόλι. </translation>
</message>
<message>
<location line="+100"/>
<location line="+24"/>
<source>Warning: The Caps Lock key is on!</source>
- <translation type="unfinished"/>
+ <translation>Προσοχη: το πλήκτρο Caps Lock είναι ενεργο.</translation>
</message>
<message>
<location line="-130"/>
@@ -312,7 +318,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+14"/>
<source>Wallet passphrase was successfully changed.</source>
- <translation type="unfinished"/>
+ <translation>Ο κωδικος του πορτοφολιού άλλαξε με επιτυχία.</translation>
</message>
</context>
<context>
@@ -405,12 +411,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+285"/>
<source>Importing blocks from disk...</source>
- <translation type="unfinished"/>
+ <translation>Εισαγωγή μπλοκ από τον σκληρο δίσκο ... </translation>
</message>
<message>
<location line="+3"/>
<source>Reindexing blocks on disk...</source>
- <translation type="unfinished"/>
+ <translation>Φόρτωση ευρετηρίου μπλοκ στον σκληρο δισκο...</translation>
</message>
<message>
<location line="-347"/>
@@ -420,7 +426,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+49"/>
<source>Modify configuration options for Bitcoin</source>
- <translation type="unfinished"/>
+ <translation>Επεργασία ρυθμισεων επιλογών για το Bitcoin</translation>
</message>
<message>
<location line="+9"/>
@@ -461,17 +467,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+101"/>
<source>&amp;Send</source>
- <translation type="unfinished"/>
+ <translation>&amp;Αποστολή</translation>
</message>
<message>
<location line="+7"/>
<source>&amp;Receive</source>
- <translation type="unfinished"/>
+ <translation>&amp;Παραλαβή </translation>
</message>
<message>
<location line="+14"/>
<source>&amp;Addresses</source>
- <translation type="unfinished"/>
+ <translation>&amp;Διεύθυνσεις</translation>
</message>
<message>
<location line="+22"/>
@@ -486,22 +492,22 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>Show or hide the main Window</source>
- <translation type="unfinished"/>
+ <translation>Εμφάνιση ή αποκρύψη του κεντρικου παράθυρου </translation>
</message>
<message>
<location line="+3"/>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished"/>
+ <translation>Κρυπτογραφήστε τα ιδιωτικά κλειδιά που ανήκουν στο πορτοφόλι σας </translation>
</message>
<message>
<location line="+7"/>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished"/>
+ <translation>Υπογράψτε ένα μήνυμα για να βεβαιώσετε πως είστε ο κάτοχος αυτής της διεύθυνσης</translation>
</message>
<message>
<location line="+2"/>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished"/>
+ <translation>Υπογράψτε ένα μήνυμα για ν&apos; αποδείξετε πως ανήκει μια συγκεκριμένη διεύθυνση Bitcoin</translation>
</message>
<message>
<location line="+28"/>
@@ -542,47 +548,47 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+22"/>
<source>No block source available...</source>
- <translation type="unfinished"/>
+ <translation>Η πηγή του μπλοκ δεν ειναι διαθέσιμη... </translation>
</message>
<message>
<location line="+12"/>
<source>Processed %1 of %2 (estimated) blocks of transaction history.</source>
- <translation type="unfinished"/>
+ <translation>Μεταποιημένα %1 απο % 2 (κατ &apos;εκτίμηση) μπλοκ της ιστορίας της συναλλαγής. </translation>
</message>
<message>
<location line="+4"/>
<source>Processed %1 blocks of transaction history.</source>
- <translation type="unfinished"/>
+ <translation>Έγινε λήψη %1 μπλοκ ιστορικού συναλλαγών</translation>
</message>
<message numerus="yes">
<location line="+20"/>
<source>%n hour(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>%n ώρες </numerusform><numerusform>%n ώρες </numerusform></translation>
</message>
<message numerus="yes">
<location line="+4"/>
<source>%n day(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>%n ημέρες </numerusform><numerusform>%n ημέρες </numerusform></translation>
</message>
<message numerus="yes">
<location line="+4"/>
<source>%n week(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>%n εβδομαδες</numerusform><numerusform>%n εβδομαδες</numerusform></translation>
</message>
<message>
<location line="+4"/>
<source>%1 behind</source>
- <translation type="unfinished"/>
+ <translation>%1 πίσω</translation>
</message>
<message>
<location line="+14"/>
<source>Last received block was generated %1 ago.</source>
- <translation type="unfinished"/>
+ <translation>Το τελευταίο μπλοκ που ελήφθη δημιουργήθηκε %1 πριν.</translation>
</message>
<message>
<location line="+2"/>
<source>Transactions after this will not yet be visible.</source>
- <translation type="unfinished"/>
+ <translation>Οι συναλλαγές μετά από αυτό δεν θα είναι ακόμη ορατες.</translation>
</message>
<message>
<location line="+22"/>
@@ -592,17 +598,19 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+3"/>
<source>Warning</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση</translation>
</message>
<message>
<location line="+3"/>
<source>Information</source>
- <translation type="unfinished"/>
+ <translation>Πληροφορία</translation>
</message>
<message>
<location line="+70"/>
<source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
- <translation type="unfinished"/>
+ <translation>Η συναλλαγή ξεπερνάει το όριο.
+Μπορεί να ολοκληρωθεί με μια αμοιβή των %1, η οποία αποδίδεται στους κόμβους που επεξεργάζονται τις συναλλαγές και βοηθούν στην υποστήριξη του δικτύου.
+Θέλετε να συνεχίσετε;</translation>
</message>
<message>
<location line="-140"/>
@@ -652,7 +660,7 @@ Address: %4
<location line="-23"/>
<location line="+23"/>
<source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation type="unfinished"/>
+ <translation>Το URI δεν μπορεί να αναλυθεί! Αυτό μπορεί να προκληθεί από μια μη έγκυρη διεύθυνση Bitcoin ή ακατάλληλη παραμέτρο URI.</translation>
</message>
<message>
<location line="+17"/>
@@ -667,7 +675,7 @@ Address: %4
<message>
<location filename="../bitcoin.cpp" line="+111"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation type="unfinished"/>
+ <translation>Παρουσιάστηκε ανεπανόρθωτο σφάλμα. Το Bitcoin δεν μπορεί πλέον να συνεχίσει με ασφάλεια και θα τερματισθει.</translation>
</message>
</context>
<context>
@@ -805,7 +813,7 @@ Address: %4
<message>
<location line="+6"/>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
- <translation type="unfinished"/>
+ <translation>Η προαιρετική αμοιβή για κάθε kB επισπεύδει την επεξεργασία των συναλλαγών σας. Οι περισσότερες συναλλαγές είναι 1 kB. </translation>
</message>
<message>
<location line="+15"/>
@@ -825,12 +833,12 @@ Address: %4
<message>
<location line="+35"/>
<source>Reset all client options to default.</source>
- <translation type="unfinished"/>
+ <translation>Επαναφορα όλων των επιλογων του πελάτη σε default.</translation>
</message>
<message>
<location line="+3"/>
<source>&amp;Reset Options</source>
- <translation type="unfinished"/>
+ <translation>Επαναφορα ρυθμίσεων</translation>
</message>
<message>
<location line="+13"/>
@@ -850,7 +858,7 @@ Address: %4
<message>
<location line="+7"/>
<source>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</source>
- <translation type="unfinished"/>
+ <translation>Σύνδεση στο Bitcoin δίκτυο μέσω διαμεσολαβητή SOCKS4 (π.χ. για σύνδεση μέσω Tor)</translation>
</message>
<message>
<location line="+3"/>
@@ -860,7 +868,7 @@ Address: %4
<message>
<location line="+9"/>
<source>Proxy &amp;IP:</source>
- <translation type="unfinished"/>
+ <translation>&amp;IP διαμεσολαβητή:</translation>
</message>
<message>
<location line="+19"/>
@@ -885,7 +893,7 @@ Address: %4
<message>
<location line="+13"/>
<source>SOCKS version of the proxy (e.g. 5)</source>
- <translation type="unfinished"/>
+ <translation>SOCKS εκδοση του διαμεσολαβητη (e.g. 5)</translation>
</message>
<message>
<location line="+36"/>
@@ -920,7 +928,7 @@ Address: %4
<message>
<location line="+8"/>
<source>User Interface &amp;language:</source>
- <translation type="unfinished"/>
+ <translation>Γλώσσα περιβάλλοντος εργασίας: </translation>
</message>
<message>
<location line="+13"/>
@@ -970,12 +978,12 @@ Address: %4
<message>
<location line="+130"/>
<source>Confirm options reset</source>
- <translation type="unfinished"/>
+ <translation>Επιβεβαιώση των επιλογων επαναφοράς </translation>
</message>
<message>
<location line="+1"/>
<source>Some settings may require a client restart to take effect.</source>
- <translation type="unfinished"/>
+ <translation>Για ορισμένες ρυθμίσεις πρεπει η επανεκκίνηση να τεθεί σε ισχύ.</translation>
</message>
<message>
<location line="+0"/>
@@ -1011,7 +1019,7 @@ Address: %4
<location line="+50"/>
<location line="+166"/>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation type="unfinished"/>
+ <translation>Οι πληροφορίες που εμφανίζονται μπορεί να είναι ξεπερασμένες. Το πορτοφόλι σας συγχρονίζεται αυτόματα με το δίκτυο Bitcoin μετά από μια σύνδεση, αλλά αυτή η διαδικασία δεν έχει ακόμη ολοκληρωθεί. </translation>
</message>
<message>
<location line="-124"/>
@@ -1036,7 +1044,7 @@ Address: %4
<message>
<location line="+13"/>
<source>Mined balance that has not yet matured</source>
- <translation type="unfinished"/>
+ <translation>Εξορυγμενο υπόλοιπο που δεν έχει ακόμα ωριμάσει </translation>
</message>
<message>
<location line="+46"/>
@@ -1065,7 +1073,7 @@ Address: %4
<message>
<location filename="../paymentserver.cpp" line="+107"/>
<source>Cannot start bitcoin: click-to-pay handler</source>
- <translation type="unfinished"/>
+ <translation>Δεν είναι δυνατή η εκκίνηση του Bitcoin: click-to-pay handler</translation>
</message>
</context>
<context>
@@ -1108,7 +1116,7 @@ Address: %4
<message>
<location line="+40"/>
<source>The entered amount is invalid, please check.</source>
- <translation type="unfinished"/>
+ <translation>Το αναγραφόμενο ποσό δεν είναι έγκυρο, παρακαλούμε να το ελέγξετε.</translation>
</message>
<message>
<location line="+23"/>
@@ -1160,7 +1168,7 @@ Address: %4
<message>
<location line="+68"/>
<source>Using OpenSSL version</source>
- <translation type="unfinished"/>
+ <translation>Χρησιμοποιηση της OpenSSL εκδοσης</translation>
</message>
<message>
<location line="+49"/>
@@ -1215,7 +1223,7 @@ Address: %4
<message>
<location line="+7"/>
<source>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</source>
- <translation type="unfinished"/>
+ <translation>Εμφανιση του Bitcoin-Qt μήνυματος βοήθειας για να πάρετε μια λίστα με τις πιθανές επιλογές Bitcoin γραμμής εντολών.</translation>
</message>
<message>
<location line="+3"/>
@@ -1235,22 +1243,22 @@ Address: %4
<message>
<location line="-104"/>
<source>Bitcoin - Debug window</source>
- <translation type="unfinished"/>
+ <translation>Bitcoin - Παράθυρο αποσφαλμάτωσης</translation>
</message>
<message>
<location line="+25"/>
<source>Bitcoin Core</source>
- <translation type="unfinished"/>
+ <translation>Bitcoin Core</translation>
</message>
<message>
<location line="+279"/>
<source>Debug log file</source>
- <translation type="unfinished"/>
+ <translation>Αρχείο καταγραφής εντοπισμού σφαλμάτων </translation>
</message>
<message>
<location line="+7"/>
<source>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation type="unfinished"/>
+ <translation>Ανοίξτε το αρχείο καταγραφής εντοπισμού σφαλμάτων από τον τρέχοντα κατάλογο δεδομένων. Αυτό μπορεί να πάρει μερικά δευτερόλεπτα για τα μεγάλα αρχεία καταγραφής. </translation>
</message>
<message>
<location line="+102"/>
@@ -1260,17 +1268,17 @@ Address: %4
<message>
<location filename="../rpcconsole.cpp" line="-30"/>
<source>Welcome to the Bitcoin RPC console.</source>
- <translation type="unfinished"/>
+ <translation>Καλώς ήρθατε στην Bitcoin RPC κονσόλα.</translation>
</message>
<message>
<location line="+1"/>
<source>Use up and down arrows to navigate history, and &lt;b&gt;Ctrl-L&lt;/b&gt; to clear screen.</source>
- <translation type="unfinished"/>
+ <translation>Χρησιμοποιήστε το πάνω και κάτω βέλος για να περιηγηθείτε στο ιστορικο, και &lt;b&gt;Ctrl-L&lt;/b&gt; για εκκαθαριση οθονης.</translation>
</message>
<message>
<location line="+1"/>
<source>Type &lt;b&gt;help&lt;/b&gt; for an overview of available commands.</source>
- <translation type="unfinished"/>
+ <translation>Γράψτε &lt;b&gt;βοήθεια&lt;/b&gt; για μια επισκόπηση των διαθέσιμων εντολών</translation>
</message>
</context>
<context>
@@ -1295,7 +1303,7 @@ Address: %4
<message>
<location line="+3"/>
<source>Add &amp;Recipient</source>
- <translation type="unfinished"/>
+ <translation>&amp;Προσθήκη αποδέκτη</translation>
</message>
<message>
<location line="+20"/>
@@ -1325,7 +1333,7 @@ Address: %4
<message>
<location line="+3"/>
<source>S&amp;end</source>
- <translation type="unfinished"/>
+ <translation>Αποστολη</translation>
</message>
<message>
<location filename="../sendcoinsdialog.cpp" line="-59"/>
@@ -1350,7 +1358,7 @@ Address: %4
<message>
<location line="+23"/>
<source>The recipient address is not valid, please recheck.</source>
- <translation type="unfinished"/>
+ <translation>Η διεύθυνση του αποδέκτη δεν είναι σωστή. Παρακαλώ ελέγξτε ξανά.</translation>
</message>
<message>
<location line="+5"/>
@@ -1375,7 +1383,7 @@ Address: %4
<message>
<location line="+5"/>
<source>Error: Transaction creation failed!</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα: Η δημιουργία της συναλλαγής απέτυχε</translation>
</message>
<message>
<location line="+5"/>
@@ -1403,7 +1411,7 @@ Address: %4
<message>
<location line="+34"/>
<source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation type="unfinished"/>
+ <translation>Διεύθυνση αποστολής της πληρωμής (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
</message>
<message>
<location line="+60"/>
@@ -1452,7 +1460,7 @@ Address: %4
<message>
<location filename="../forms/signverifymessagedialog.ui" line="+14"/>
<source>Signatures - Sign / Verify a Message</source>
- <translation type="unfinished"/>
+ <translation>Υπογραφές - Είσοδος / Επαλήθευση μήνυματος </translation>
</message>
<message>
<location line="+13"/>
@@ -1504,7 +1512,7 @@ Address: %4
<message>
<location line="+27"/>
<source>Copy the current signature to the system clipboard</source>
- <translation type="unfinished"/>
+ <translation>Αντέγραφη της επιλεγμενης διεύθυνσης στο πρόχειρο του συστηματος</translation>
</message>
<message>
<location line="+21"/>
@@ -1514,12 +1522,12 @@ Address: %4
<message>
<location line="+3"/>
<source>Sign &amp;Message</source>
- <translation type="unfinished"/>
+ <translation>Υπογραφη μήνυματος</translation>
</message>
<message>
<location line="+14"/>
<source>Reset all sign message fields</source>
- <translation type="unfinished"/>
+ <translation>Επαναφορά όλων των πεδίων μήνυματος</translation>
</message>
<message>
<location line="+3"/>
@@ -1535,7 +1543,7 @@ Address: %4
<message>
<location line="+6"/>
<source>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</source>
- <translation type="unfinished"/>
+ <translation>Πληκτρολογήστε την υπογραφή διεύθυνσης, μήνυμα (βεβαιωθείτε ότι έχετε αντιγράψει τις αλλαγές γραμμής, κενά, tabs, κ.λπ. ακριβώς) και την υπογραφή παρακάτω, για να ελέγξει το μήνυμα. Να είστε προσεκτικοί για να μην διαβάσετε περισσότερα στην υπογραφή ό, τι είναι στην υπογραφή ίδιο το μήνυμα , για να μην εξαπατηθούν από έναν άνθρωπο -in - the-middle επίθεση.</translation>
</message>
<message>
<location line="+21"/>
@@ -1545,17 +1553,17 @@ Address: %4
<message>
<location line="+40"/>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation type="unfinished"/>
+ <translation>Υπογράψτε ένα μήνυμα για ν&apos; αποδείξετε πως υπογραφθηκε απο μια συγκεκριμένη διεύθυνση Bitcoin</translation>
</message>
<message>
<location line="+3"/>
<source>Verify &amp;Message</source>
- <translation type="unfinished"/>
+ <translation>Επιβεβαίωση μηνύματος</translation>
</message>
<message>
<location line="+14"/>
<source>Reset all verify message fields</source>
- <translation type="unfinished"/>
+ <translation>Επαναφορά όλων επαλήθευμενων πεδίων μήνυματος </translation>
</message>
<message>
<location filename="../signverifymessagedialog.cpp" line="+27"/>
@@ -1566,7 +1574,7 @@ Address: %4
<message>
<location line="-2"/>
<source>Click &quot;Sign Message&quot; to generate signature</source>
- <translation type="unfinished"/>
+ <translation>Κάντε κλικ στο &quot;Υπογραφή Μηνύματος&quot; για να λάβετε την υπογραφή</translation>
</message>
<message>
<location line="+3"/>
@@ -1591,17 +1599,17 @@ Address: %4
<location line="-81"/>
<location line="+81"/>
<source>The entered address does not refer to a key.</source>
- <translation type="unfinished"/>
+ <translation>Η διεύθυνση που έχει εισαχθεί δεν αναφέρεται σε ένα πλήκτρο.</translation>
</message>
<message>
<location line="-73"/>
<source>Wallet unlock was cancelled.</source>
- <translation type="unfinished"/>
+ <translation>το ξεκλείδωμα του πορτοφολιού απέτυχε</translation>
</message>
<message>
<location line="+8"/>
<source>Private key for the entered address is not available.</source>
- <translation type="unfinished"/>
+ <translation>Το προσωπικό κλειδί εισαγμενης διευθυνσης δεν είναι διαθέσιμο.</translation>
</message>
<message>
<location line="+12"/>
@@ -1627,7 +1635,7 @@ Address: %4
<message>
<location line="+0"/>
<source>The signature did not match the message digest.</source>
- <translation type="unfinished"/>
+ <translation>Η υπογραφή δεν ταιριάζει με το μήνυμα. </translation>
</message>
<message>
<location line="+7"/>
@@ -1645,7 +1653,7 @@ Address: %4
<message>
<location filename="../splashscreen.cpp" line="+22"/>
<source>The Bitcoin developers</source>
- <translation type="unfinished"/>
+ <translation>Οι Bitcoin προγραμματιστές </translation>
</message>
<message>
<location line="+1"/>
@@ -1683,7 +1691,7 @@ Address: %4
<message numerus="yes">
<location line="+7"/>
<source>, broadcast through %n node(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>, έχει μεταδοθεί μέσω %n κόμβων</numerusform><numerusform>, έχει μεταδοθεί μέσω %n κόμβων</numerusform></translation>
</message>
<message>
<location line="+4"/>
@@ -1698,7 +1706,7 @@ Address: %4
<message>
<location line="+0"/>
<source>Generated</source>
- <translation type="unfinished"/>
+ <translation>Δημιουργία </translation>
</message>
<message>
<location line="+5"/>
@@ -1717,7 +1725,7 @@ Address: %4
<location line="-77"/>
<location line="+2"/>
<source>own address</source>
- <translation type="unfinished"/>
+ <translation> δική σας διεύθυνση </translation>
</message>
<message>
<location line="-2"/>
@@ -1731,17 +1739,17 @@ Address: %4
<location line="+17"/>
<location line="+30"/>
<source>Credit</source>
- <translation type="unfinished"/>
+ <translation>Πίστωση </translation>
</message>
<message numerus="yes">
<location line="-102"/>
<source>matures in %n more block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>ωρίμανση σε %n επιπλέον μπλοκ</numerusform><numerusform>ωρίμανση σε %n επιπλέον μπλοκ</numerusform></translation>
</message>
<message>
<location line="+2"/>
<source>not accepted</source>
- <translation type="unfinished"/>
+ <translation>μη αποδεκτό</translation>
</message>
<message>
<location line="+44"/>
@@ -1749,17 +1757,17 @@ Address: %4
<location line="+15"/>
<location line="+30"/>
<source>Debit</source>
- <translation type="unfinished"/>
+ <translation>Debit</translation>
</message>
<message>
<location line="-39"/>
<source>Transaction fee</source>
- <translation type="unfinished"/>
+ <translation>Τέλος συναλλαγής </translation>
</message>
<message>
<location line="+16"/>
<source>Net amount</source>
- <translation type="unfinished"/>
+ <translation>Καθαρό ποσό</translation>
</message>
<message>
<location line="+6"/>
@@ -1779,7 +1787,7 @@ Address: %4
<message>
<location line="+3"/>
<source>Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation type="unfinished"/>
+ <translation>Πρέπει να περιμένετε 120 μπλοκ πριν μπορέσετε να χρησιμοποιήσετε τα νομίσματα που έχετε δημιουργήσει. Το μπλοκ που δημιουργήσατε μεταδόθηκε στο δίκτυο για να συμπεριληφθεί στην αλυσίδα των μπλοκ. Αν δεν μπει σε αυτή θα μετατραπεί σε &quot;μη αποδεκτό&quot; και δε θα μπορεί να καταναλωθεί. Αυτό συμβαίνει σπάνια όταν κάποιος άλλος κόμβος δημιουργήσει ένα μπλοκ λίγα δευτερόλεπτα πριν από εσάς.</translation>
</message>
<message>
<location line="+7"/>
@@ -1794,7 +1802,7 @@ Address: %4
<message>
<location line="+3"/>
<source>Inputs</source>
- <translation type="unfinished"/>
+ <translation>εισροές </translation>
</message>
<message>
<location line="+23"/>
@@ -1804,12 +1812,12 @@ Address: %4
<message>
<location line="+1"/>
<source>true</source>
- <translation type="unfinished"/>
+ <translation>αληθής</translation>
</message>
<message>
<location line="+0"/>
<source>false</source>
- <translation type="unfinished"/>
+ <translation>αναληθής </translation>
</message>
<message>
<location line="-209"/>
@@ -1819,7 +1827,7 @@ Address: %4
<message numerus="yes">
<location line="-35"/>
<source>Open for %n more block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>Ανοιχτό για %n μπλοκ</numerusform><numerusform>Ανοιχτό για %n μπλοκ</numerusform></translation>
</message>
<message>
<location line="+70"/>
@@ -1865,7 +1873,7 @@ Address: %4
<message numerus="yes">
<location line="+57"/>
<source>Open for %n more block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>Ανοιχτό για %n μπλοκ</numerusform><numerusform>Ανοιχτό για %n μπλοκ</numerusform></translation>
</message>
<message>
<location line="+3"/>
@@ -1890,7 +1898,7 @@ Address: %4
<message numerus="yes">
<location line="+8"/>
<source>Mined balance will be available when it matures in %n more block(s)</source>
- <translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
+ <translation><numerusform>Το υπόλοιπο από την εξόρυξη θα είναι διαθέσιμο μετά από %n μπλοκ</numerusform><numerusform>Το υπόλοιπο από την εξόρυξη θα είναι διαθέσιμο μετά από %n μπλοκ</numerusform></translation>
</message>
<message>
<location line="+5"/>
@@ -2049,7 +2057,7 @@ Address: %4
<message>
<location line="+1"/>
<source>Copy transaction ID</source>
- <translation type="unfinished"/>
+ <translation>Αντιγραφη του ID Συναλλαγής</translation>
</message>
<message>
<location line="+1"/>
@@ -2140,7 +2148,7 @@ Address: %4
<message>
<location filename="../walletview.cpp" line="+42"/>
<source>&amp;Export</source>
- <translation type="unfinished"/>
+ <translation>&amp;Εξαγωγή</translation>
</message>
<message>
<location line="+1"/>
@@ -2150,32 +2158,32 @@ Address: %4
<message>
<location line="+193"/>
<source>Backup Wallet</source>
- <translation type="unfinished"/>
+ <translation>Αντίγραφο ασφαλείας του πορτοφολιού</translation>
</message>
<message>
<location line="+0"/>
<source>Wallet Data (*.dat)</source>
- <translation type="unfinished"/>
+ <translation>Αρχεία δεδομένων πορτοφολιού (*.dat)</translation>
</message>
<message>
<location line="+3"/>
<source>Backup Failed</source>
- <translation type="unfinished"/>
+ <translation>Αποτυχία κατά τη δημιουργία αντιγράφου</translation>
</message>
<message>
<location line="+0"/>
<source>There was an error trying to save the wallet data to the new location.</source>
- <translation type="unfinished"/>
+ <translation>Παρουσιάστηκε σφάλμα κατά την αποθήκευση των δεδομένων πορτοφολιού στη νέα τοποθεσία.</translation>
</message>
<message>
<location line="+4"/>
<source>Backup Successful</source>
- <translation type="unfinished"/>
+ <translation>Η δημιουργια αντιγραφου ασφαλειας πετυχε</translation>
</message>
<message>
<location line="+0"/>
<source>The wallet data was successfully saved to the new location.</source>
- <translation type="unfinished"/>
+ <translation>Τα δεδομένα πορτοφόλιου αποθηκεύτηκαν με επιτυχία στη νέα θέση. </translation>
</message>
</context>
<context>
@@ -2243,7 +2251,7 @@ Address: %4
<message>
<location line="-48"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
- <translation type="unfinished"/>
+ <translation>Σύνδεση σε έναν κόμβο για την ανάκτηση διευθύνσεων από ομοτίμους, και αποσυνδέσh</translation>
</message>
<message>
<location line="+82"/>
@@ -2263,7 +2271,7 @@ Address: %4
<message>
<location line="-29"/>
<source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
- <translation type="unfinished"/>
+ <translation>Ένα σφάλμα συνέβη καθώς προετοιμαζόταν η πόρτα RPC %u για αναμονή IPv4: %s</translation>
</message>
<message>
<location line="+27"/>
@@ -2288,7 +2296,7 @@ Address: %4
<message>
<location line="-112"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
- <translation type="unfinished"/>
+ <translation>Να δέχεσαι συνδέσεις από έξω(προεπιλογή:1)</translation>
</message>
<message>
<location line="-80"/>
@@ -2303,87 +2311,98 @@ If the file does not exist, create it with owner-readable-only file permissions.
It is also recommended to set alertnotify so you are notified of problems;
for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
</source>
- <translation type="unfinished"/>
+ <translation>%s, you must set a rpcpassword in the configuration file:
+%s
+It is recommended you use the following random password:
+rpcuser=bitcoinrpc
+rpcpassword=%s
+(you do not need to remember this password)
+The username and password MUST NOT be the same.
+If the file does not exist, create it with owner-readable-only file permissions.
+It is also recommended to set alertnotify so you are notified of problems;
+for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
+</translation>
</message>
<message>
<location line="+17"/>
<source>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</source>
- <translation type="unfinished"/>
+ <translation>Ένα σφάλμα συνέβη καθώς προετοιμαζόταν η υποδοχη RPC %u για αναμονη του IPv6, επεσε πισω στο IPv4:%s</translation>
</message>
<message>
<location line="+3"/>
<source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
- <translation type="unfinished"/>
+ <translation>Αποθηκευση σε συγκεκριμένη διεύθυνση. Χρησιμοποιήστε τα πλήκτρα [Host] : συμβολισμός θύρα για IPv6</translation>
</message>
<message>
<location line="+3"/>
<source>Cannot obtain a lock on data directory %s. Bitcoin is probably already running.</source>
- <translation type="unfinished"/>
+ <translation>Αδυναμία κλειδώματος του φακέλου δεδομένων %s. Πιθανώς το Bitcoin να είναι ήδη ενεργό.</translation>
</message>
<message>
<location line="+3"/>
<source>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.</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα: Η συναλλαγή απορρίφθηκε.
+Αυτό ίσως οφείλεται στο ότι τα νομίσματά σας έχουν ήδη ξοδευτεί, π.χ. με την αντιγραφή του wallet.dat σε άλλο σύστημα και την χρήση τους εκεί, χωρίς η συναλλαγή να έχει καταγραφεί στο παρόν σύστημα.</translation>
</message>
<message>
<location line="+4"/>
<source>Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα: Αυτή η συναλλαγή απαιτεί αμοιβή συναλλαγής τουλάχιστον %s λόγω του μεγέθους, πολυπλοκότητας ή της χρήσης πρόσφατης παραλαβής κεφαλαίου</translation>
</message>
<message>
<location line="+3"/>
<source>Execute command when a relevant alert is received (%s in cmd is replaced by message)</source>
- <translation type="unfinished"/>
+ <translation>Εκτέλεση της εντολής όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ)</translation>
</message>
<message>
<location line="+3"/>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
- <translation type="unfinished"/>
+ <translation>Εκτέλεσε την εντολή όταν το καλύτερο μπλοκ αλλάξει(%s στην εντολή αντικαθίσταται από το hash του μπλοκ)</translation>
</message>
<message>
<location line="+11"/>
<source>Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)</source>
- <translation type="unfinished"/>
+ <translation>Ορίστε το μέγιστο μέγεθος των high-priority/low-fee συναλλαγων σε bytes (προεπιλογή: 27000)</translation>
</message>
<message>
<location line="+6"/>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation type="unfinished"/>
+ <translation>Αυτό είναι ένα προ-τεστ κυκλοφορίας - χρησιμοποιήστε το με δική σας ευθύνη - δεν χρησιμοποιείτε για εξόρυξη ή για αλλες εφαρμογές</translation>
</message>
<message>
<location line="+5"/>
<source>Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση: Η παράμετρος -paytxfee είναι πολύ υψηλή. Πρόκειται για την αμοιβή που θα πληρώνετε για κάθε συναλλαγή που θα στέλνετε.</translation>
</message>
<message>
<location line="+3"/>
<source>Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση: Εμφανίσεις συναλλαγων δεν μπορεί να είναι σωστες! Μπορεί να χρειαστεί να αναβαθμίσετε, ή άλλοι κόμβοι μπορεί να χρειαστεί να αναβαθμίστουν. </translation>
</message>
<message>
<location line="+3"/>
<source>Warning: Please check that your computer&apos;s date and time are correct! If your clock is wrong Bitcoin will not work properly.</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση: Παρακαλώ βεβαιωθείτε πως η ημερομηνία κι ώρα του συστήματός σας είναι σωστές. Αν το ρολόι του υπολογιστή σας πάει λάθος, ενδέχεται να μη λειτουργεί σωστά το Bitcoin.</translation>
</message>
<message>
<location line="+3"/>
<source>Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση : Σφάλμα wallet.dat κατα την ανάγνωση ! Όλα τα κλειδιά αναγνωρισθηκαν σωστά, αλλά τα δεδομένα των συναλλαγών ή καταχωρήσεις στο βιβλίο διευθύνσεων μπορεί να είναι ελλιπείς ή λανθασμένα. </translation>
</message>
<message>
<location line="+3"/>
<source>Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση : το αρχειο wallet.dat ειναι διεφθαρμένο, τα δεδομένα σώζονται ! Original wallet.dat αποθηκεύονται ως πορτοφόλι { timestamp } bak στο % s ? . . Αν το υπόλοιπο του ή τις συναλλαγές σας, είναι λάθος θα πρέπει να επαναφέρετε από ένα αντίγραφο ασφαλείας</translation>
</message>
<message>
<location line="+14"/>
<source>Attempt to recover private keys from a corrupt wallet.dat</source>
- <translation type="unfinished"/>
+ <translation>Προσπάθεια για ανακτησει ιδιωτικων κλειδιων από ενα διεφθαρμένο αρχειο wallet.dat </translation>
</message>
<message>
<location line="+2"/>
<source>Block creation options:</source>
- <translation type="unfinished"/>
+ <translation>Αποκλεισμός επιλογων δημιουργίας: </translation>
</message>
<message>
<location line="+5"/>
@@ -2393,47 +2412,47 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+3"/>
<source>Corrupted block database detected</source>
- <translation type="unfinished"/>
+ <translation>Εντοπισθηκε διεφθαρμενη βαση δεδομενων των μπλοκ</translation>
</message>
<message>
<location line="+1"/>
<source>Discover own IP address (default: 1 when listening and no -externalip)</source>
- <translation type="unfinished"/>
+ <translation>Ανακαλύψτε την δικη σας IP διεύθυνση (προεπιλογή: 1 όταν ακούει και δεν - externalip) </translation>
</message>
<message>
<location line="+1"/>
<source>Do you want to rebuild the block database now?</source>
- <translation type="unfinished"/>
+ <translation>Θελετε να δημιουργηθει τωρα η βαση δεδομενων του μπλοκ? </translation>
</message>
<message>
<location line="+2"/>
<source>Error initializing block database</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων μπλοκ</translation>
</message>
<message>
<location line="+1"/>
<source>Error initializing wallet database environment %s!</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα κατά την ενεργοποίηση της βάσης δεδομένων πορτοφόλιου %s!</translation>
</message>
<message>
<location line="+1"/>
<source>Error loading block database</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα φορτωσης της βασης δεδομενων των μπλοκ</translation>
</message>
<message>
<location line="+4"/>
<source>Error opening block database</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα φορτωσης της βασης δεδομενων των μπλοκ</translation>
</message>
<message>
<location line="+2"/>
<source>Error: Disk space is low!</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση: Χαμηλός χώρος στο δίσκο </translation>
</message>
<message>
<location line="+1"/>
<source>Error: Wallet locked, unable to create transaction!</source>
- <translation type="unfinished"/>
+ <translation>Σφάλμα: το πορτοφόλι είναι κλειδωμένο, δεν μπορεί να δημιουργηθεί συναλλαγή</translation>
</message>
<message>
<location line="+1"/>
@@ -2443,167 +2462,167 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+1"/>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation type="unfinished"/>
+ <translation>ταλαιπωρηθειτε για να ακούσετε σε οποιαδήποτε θύρα. Χρήση - ακούστε = 0 , αν θέλετε αυτό.</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to read block info</source>
- <translation type="unfinished"/>
+ <translation>Αποτυχία αναγνωσης των block πληροφοριων</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to read block</source>
- <translation type="unfinished"/>
+ <translation>Η αναγνωση του μπλοκ απετυχε</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to sync block index</source>
- <translation type="unfinished"/>
+ <translation>Ο συγχρονισμος του μπλοκ ευρετηριου απετυχε</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write block index</source>
- <translation type="unfinished"/>
+ <translation>Η δημιουργια του μπλοκ ευρετηριου απετυχε</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write block info</source>
- <translation type="unfinished"/>
+ <translation>Η δημιουργια των μπλοκ πληροφοριων απετυχε</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write block</source>
- <translation type="unfinished"/>
+ <translation>Η δημιουργια του μπλοκ απετυχε</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write file info</source>
- <translation type="unfinished"/>
+ <translation>Αδυναμία εγγραφής πληροφοριων αρχειου</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write to coin database</source>
- <translation type="unfinished"/>
+ <translation>Αποτυχία εγγραφής στη βάση δεδομένων νομίσματος</translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write transaction index</source>
- <translation type="unfinished"/>
+ <translation>Αποτυχία εγγραφής δείκτη συναλλαγών </translation>
</message>
<message>
<location line="+1"/>
<source>Failed to write undo data</source>
- <translation type="unfinished"/>
+ <translation>Αποτυχία εγγραφής αναίρεσης δεδομένων </translation>
</message>
<message>
<location line="+2"/>
<source>Find peers using DNS lookup (default: 1 unless -connect)</source>
- <translation type="unfinished"/>
+ <translation>Βρες ομότιμους υπολογιστές χρησιμοποιώντας αναζήτηση DNS(προεπιλογή:1)</translation>
</message>
<message>
<location line="+1"/>
<source>Generate coins (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Δημιουργία νομισμάτων (προκαθορισμος: 0)</translation>
</message>
<message>
<location line="+2"/>
<source>How many blocks to check at startup (default: 288, 0 = all)</source>
- <translation type="unfinished"/>
+ <translation>Πόσα μπλοκ να ελέγχθουν κατά την εκκίνηση (προεπιλογή:288,0=όλα)</translation>
</message>
<message>
<location line="+1"/>
<source>How thorough the block verification is (0-4, default: 3)</source>
- <translation type="unfinished"/>
+ <translation>Πόσο εξονυχιστική να είναι η επιβεβαίωση του μπλοκ(0-4, προεπιλογή:3)</translation>
</message>
<message>
<location line="+19"/>
<source>Not enough file descriptors available.</source>
- <translation type="unfinished"/>
+ <translation>Δεν ειναι αρκετες περιγραφες αρχείων διαθέσιμες.</translation>
</message>
<message>
<location line="+8"/>
<source>Rebuild block chain index from current blk000??.dat files</source>
- <translation type="unfinished"/>
+ <translation>Εισαγωγή μπλοκ από εξωτερικό αρχείο blk000?.dat</translation>
</message>
<message>
<location line="+16"/>
<source>Set the number of threads to service RPC calls (default: 4)</source>
- <translation type="unfinished"/>
+ <translation>Ορίσμος του αριθμόυ θεματων στην υπηρεσία κλήσεων RPC (προεπιλογή: 4) </translation>
</message>
<message>
<location line="+26"/>
<source>Verifying blocks...</source>
- <translation type="unfinished"/>
+ <translation>Επαλήθευση των μπλοκ... </translation>
</message>
<message>
<location line="+1"/>
<source>Verifying wallet...</source>
- <translation type="unfinished"/>
+ <translation>Επαλήθευση πορτοφολιου... </translation>
</message>
<message>
<location line="-69"/>
<source>Imports blocks from external blk000??.dat file</source>
- <translation type="unfinished"/>
+ <translation>Εισαγωγή μπλοκ από εξωτερικό αρχείο blk000?.dat</translation>
</message>
<message>
<location line="-76"/>
<source>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Ορίσμος του αριθμό των νημάτων ελέγχου σεναρίου (μέχρι 16, 0 = auto, &lt;0 = αφήνουν τους πολλους πυρήνες δωρεάν, default: 0)</translation>
</message>
<message>
<location line="+77"/>
<source>Information</source>
- <translation type="unfinished"/>
+ <translation>Πληροφορία</translation>
</message>
<message>
<location line="+3"/>
<source>Invalid -tor address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Δεν είναι έγκυρη η διεύθυνση διαμεσολαβητή: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Μη έγκυρο ποσό για την παράμετρο -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Μη έγκυρο ποσό για την παράμετρο -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+8"/>
<source>Maintain a full transaction index (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Διατηρήση ένος πλήρες ευρετήριου συναλλαγών (προεπιλογή: 0) </translation>
</message>
<message>
<location line="+2"/>
<source>Maximum per-connection receive buffer, &lt;n&gt;*1000 bytes (default: 5000)</source>
- <translation type="unfinished"/>
+ <translation>Μέγιστος buffer λήψης ανά σύνδεση, &lt;n&gt;*1000 bytes (προεπιλογή: 5000)</translation>
</message>
<message>
<location line="+1"/>
<source>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: 1000)</source>
- <translation type="unfinished"/>
+ <translation>Μέγιστος buffer αποστολής ανά σύνδεση, &lt;n&gt;*1000 bytes (προεπιλογή: 1000)</translation>
</message>
<message>
<location line="+2"/>
<source>Only accept block chain matching built-in checkpoints (default: 1)</source>
- <translation type="unfinished"/>
+ <translation>Μονο αποδοχη αλυσίδας μπλοκ που ταιριάζει με τα ενσωματωμένα σημεία ελέγχου (προεπιλογή: 1) </translation>
</message>
<message>
<location line="+1"/>
<source>Only connect to nodes in network &lt;net&gt; (IPv4, IPv6 or Tor)</source>
- <translation type="unfinished"/>
+ <translation> Συνδέση μόνο σε κόμβους του δικτύου &lt;net&gt; (IPv4, IPv6 ή Tor) </translation>
</message>
<message>
<location line="+2"/>
<source>Output extra debugging information. Implies all other -debug* options</source>
- <translation type="unfinished"/>
+ <translation>Έξοδος επιπλέον πληροφοριών εντοπισμού σφαλμάτων</translation>
</message>
<message>
<location line="+1"/>
<source>Output extra network debugging information</source>
- <translation type="unfinished"/>
+ <translation>Έξοδος επιπλέον πληροφοριών εντοπισμού σφαλμάτων</translation>
</message>
<message>
<location line="+2"/>
@@ -2613,12 +2632,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+5"/>
<source>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
- <translation type="unfinished"/>
+ <translation>Ρυθμίσεις SSL: (ανατρέξτε στο Bitcoin Wiki για οδηγίες ρυθμίσεων SSL)</translation>
</message>
<message>
<location line="+1"/>
<source>Select the version of socks proxy to use (4-5, default: 5)</source>
- <translation type="unfinished"/>
+ <translation>Επιλέξτε την έκδοση του διαμεσολαβητη για να χρησιμοποιήσετε (4-5 , προεπιλογή: 5)</translation>
</message>
<message>
<location line="+3"/>
@@ -2633,22 +2652,22 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+5"/>
<source>Set maximum block size in bytes (default: 250000)</source>
- <translation type="unfinished"/>
+ <translation>Ορίσμος του μέγιστου μέγεθος block σε bytes (προεπιλογή: 250000)</translation>
</message>
<message>
<location line="+1"/>
<source>Set minimum block size in bytes (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Ορίστε το μέγιστο μέγεθος block σε bytes (προεπιλογή: 0)</translation>
</message>
<message>
<location line="+2"/>
<source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
- <translation type="unfinished"/>
+ <translation>Συρρίκνωση του αρχείο debug.log κατα την εκκίνηση του πελάτη (προεπιλογή: 1 όταν δεν-debug)</translation>
</message>
<message>
<location line="+1"/>
<source>Signing transaction failed</source>
- <translation type="unfinished"/>
+ <translation>Η υπογραφή συναλλαγής απέτυχε </translation>
</message>
<message>
<location line="+2"/>
@@ -2663,32 +2682,32 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+4"/>
<source>Transaction amount too small</source>
- <translation type="unfinished"/>
+ <translation>Το ποσό της συναλλαγής είναι πολύ μικρο </translation>
</message>
<message>
<location line="+1"/>
<source>Transaction amounts must be positive</source>
- <translation type="unfinished"/>
+ <translation>Τα ποσά των συναλλαγών πρέπει να είναι θετικα</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction too large</source>
- <translation type="unfinished"/>
+ <translation>Η συναλλαγή ειναι πολύ μεγάλη </translation>
</message>
<message>
<location line="+7"/>
<source>Use UPnP to map the listening port (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Χρησιμοποίηση του UPnP για την χρήση της πόρτας αναμονής (προεπιλογή:0)</translation>
</message>
<message>
<location line="+1"/>
<source>Use UPnP to map the listening port (default: 1 when listening)</source>
- <translation type="unfinished"/>
+ <translation>Χρησιμοποίηση του UPnP για την χρήση της πόρτας αναμονής (προεπιλογή:1)</translation>
</message>
<message>
<location line="+1"/>
<source>Use proxy to reach tor hidden services (default: same as -proxy)</source>
- <translation type="unfinished"/>
+ <translation>Χρήση διακομιστή μεσολάβησης για την επίτευξη των Tor κρυμμένων υπηρεσιων (προεπιλογή: ίδιο με το-proxy) </translation>
</message>
<message>
<location line="+2"/>
@@ -2698,22 +2717,22 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+4"/>
<source>Warning</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση</translation>
</message>
<message>
<location line="+1"/>
<source>Warning: This version is obsolete, upgrade required!</source>
- <translation type="unfinished"/>
+ <translation>Προειδοποίηση: Αυτή η έκδοση είναι ξεπερασμένη, απαιτείται αναβάθμιση </translation>
</message>
<message>
<location line="+1"/>
<source>You need to rebuild the databases using -reindex to change -txindex</source>
- <translation type="unfinished"/>
+ <translation>Θα πρέπει να ξαναχτίστουν οι βάσεις δεδομένων που χρησιμοποιούντε-Αναδημιουργία αλλάγων-txindex </translation>
</message>
<message>
<location line="+1"/>
<source>wallet.dat corrupt, salvage failed</source>
- <translation type="unfinished"/>
+ <translation>Το αρχειο wallet.dat ειναι διεφθαρμένο, η διάσωση απέτυχε</translation>
</message>
<message>
<location line="-50"/>
@@ -2778,7 +2797,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+6"/>
<source>Unable to bind to %s on this computer (bind returned error %d, %s)</source>
- <translation type="unfinished"/>
+ <translation>Αδύνατη η σύνδεση με τη θύρα %s αυτού του υπολογιστή (bind returned error %d, %s) </translation>
</message>
<message>
<location line="-91"/>
@@ -2788,7 +2807,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-10"/>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
- <translation type="unfinished"/>
+ <translation>Να επιτρέπονται οι έλεγχοι DNS για προσθήκη και σύνδεση κόμβων</translation>
</message>
<message>
<location line="+55"/>
@@ -2823,27 +2842,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+56"/>
<source>Unknown network specified in -onlynet: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Άγνωστo δίκτυο ορίζεται σε onlynet: &apos;%s&apos;</translation>
</message>
<message>
<location line="-1"/>
<source>Unknown -socks proxy version requested: %i</source>
- <translation type="unfinished"/>
+ <translation>Άγνωστo δίκτυο ορίζεται: %i</translation>
</message>
<message>
<location line="-96"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Cannot resolve -externalip address: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Δεν μπορώ να γράψω την προεπιλεγμένη διεύθυνση: &apos;%s&apos;</translation>
</message>
<message>
<location line="+44"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Μη έγκυρο ποσό για την παράμετρο -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
@@ -2868,7 +2887,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-25"/>
<source>Unable to bind to %s on this computer. Bitcoin is probably already running.</source>
- <translation type="unfinished"/>
+ <translation>Αδύνατη η σύνδεση με τη θύρα %s αυτού του υπολογιστή. Το Bitcoin είναι πιθανώς ήδη ενεργό.</translation>
</message>
<message>
<location line="+64"/>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index 26e3993dd3..7c584e954a 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -71,7 +71,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location filename="../addressbookpage.cpp" line="+63"/>
<source>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</source>
- <translation>Estas son tus direcciones Bitcoin para recibir pagos. Puedes utilizar una diferente por cada persona emisora para saber quién te está pagando.</translation>
+ <translation>Estas son sus direcciones Bitcoin para recibir pagos. Puede utilizar una diferente por cada persona emisora para saber quién le está pagando.</translation>
</message>
<message>
<location filename="../forms/addressbookpage.ui" line="+14"/>
@@ -262,7 +262,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+15"/>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation>IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su fichero de billetera debe reemplazarse con el fichero de billetera encriptado recientemente creado. Por razones de seguridad, las copias de seguridad previas del fichero de billetera que no estaban encriptadas pasarán a estar inservibles en cuanto comience a usar la nueva billetera encriptada.</translation>
+ <translation>IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado.</translation>
</message>
<message>
<location line="+100"/>
@@ -504,7 +504,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+7"/>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Firmar mensajes con sus direcciones Bitcoin para probar la propiedad</translation>
+ <translation>Firmar mensajes con sus direcciones Bitcoin para demostrar la propiedad</translation>
</message>
<message>
<location line="+2"/>
@@ -550,12 +550,12 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+22"/>
<source>No block source available...</source>
- <translation>Ninguna origen de bloque disponible ...</translation>
+ <translation>Ninguna fuente de bloques disponible ...</translation>
</message>
<message>
<location line="+12"/>
<source>Processed %1 of %2 (estimated) blocks of transaction history.</source>
- <translation>Se han procesado %1 de %2 (estimación) bloques de historia de transacción.</translation>
+ <translation>Se han procesado %1 de %2 bloques (estimados) del historial de transacciones.</translation>
</message>
<message>
<location line="+4"/>
@@ -580,7 +580,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+4"/>
<source>%1 behind</source>
- <translation>%1 detrás</translation>
+ <translation>%1 atrás</translation>
</message>
<message>
<location line="+14"/>
@@ -590,7 +590,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+2"/>
<source>Transactions after this will not yet be visible.</source>
- <translation>Las transacciones que vengan después de esta todavía no serán visibles.</translation>
+ <translation>Las transacciones posteriores a esta aún no están visibles.</translation>
</message>
<message>
<location line="+22"/>
@@ -620,7 +620,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard.</t
<message>
<location line="+31"/>
<source>Catching up...</source>
- <translation>Recuperando...</translation>
+ <translation>Actualizando...</translation>
</message>
<message>
<location line="+113"/>
@@ -813,7 +813,7 @@ Dirección: %4
<message>
<location line="+6"/>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
- <translation>Tarifa de transacción opcional por kB que ayuda a asegurar que tus transacciones sean procesadas rápidamente. La mayoría de transacciones son de 1kB.</translation>
+ <translation>Tarifa de transacción opcional por kB que ayuda a asegurar que sus transacciones sean procesadas rápidamente. La mayoría de transacciones son de 1kB.</translation>
</message>
<message>
<location line="+15"/>
@@ -1054,7 +1054,7 @@ Dirección: %4
<message>
<location line="-101"/>
<source>Your current balance</source>
- <translation>Saldo actual</translation>
+ <translation>Su saldo actual</translation>
</message>
<message>
<location line="+29"/>
@@ -2399,7 +2399,7 @@ Por ejemplo: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+3"/>
<source>Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Aviso: ¿Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de respaldo.</translation>
+ <translation>Aviso: ¡Recuperados datos de wallet.dat corrupto! El wallet.dat original se ha guardado como wallet.{timestamp}.bak en %s; si hubiera errores en su saldo o transacciones, deberá restaurar una copia de seguridad.</translation>
</message>
<message>
<location line="+14"/>
@@ -2929,7 +2929,7 @@ Por ejemplo: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+64"/>
<source>Rescanning...</source>
- <translation>Rescaneando...</translation>
+ <translation>Reexplorando...</translation>
</message>
<message>
<location line="-57"/>
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index 93ac949e72..d7d0b7c78c 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -43,12 +43,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+19"/>
<source>Double-click to edit address or label</source>
- <translation>アドレスかレーベルを編集するのためにダブルクリックして</translation>
+ <translation>アドレスまたはラベルを編集するにはダブルクリック</translation>
</message>
<message>
<location line="+27"/>
<source>Create a new address</source>
- <translation>新しいのアドレスを作る</translation>
+ <translation>新規アドレスの作成</translation>
</message>
<message>
<location line="+14"/>
@@ -113,7 +113,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+14"/>
<source>&amp;Delete</source>
- <translation>&amp;消す</translation>
+ <translation>削除(&amp;D)</translation>
</message>
<message>
<location filename="../addressbookpage.cpp" line="-5"/>
@@ -138,17 +138,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+260"/>
<source>Export Address Book Data</source>
- <translation>アドレス帳データーを輸出する</translation>
+ <translation>アドレス帳データをエクスポートする</translation>
</message>
<message>
<location line="+1"/>
<source>Comma separated file (*.csv)</source>
- <translation>テキスト CSV (*.csv)</translation>
+ <translation>CSVファイル (*.csv)</translation>
</message>
<message>
<location line="+13"/>
<source>Error exporting</source>
- <translation>エラー輸出</translation>
+ <translation>エクスポートエラー</translation>
</message>
<message>
<location line="+0"/>
@@ -161,7 +161,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location filename="../addresstablemodel.cpp" line="+144"/>
<source>Label</source>
- <translation>レーベル</translation>
+ <translation>ラベル</translation>
</message>
<message>
<location line="+0"/>
@@ -171,7 +171,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+36"/>
<source>(no label)</source>
- <translation>(レーベル無し)</translation>
+ <translation>(ラベル無し)</translation>
</message>
</context>
<context>
@@ -184,62 +184,62 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+21"/>
<source>Enter passphrase</source>
- <translation>パスフレーズを入って</translation>
+ <translation>パスフレーズを入力</translation>
</message>
<message>
<location line="+14"/>
<source>New passphrase</source>
- <translation>新しいのパスフレーズ</translation>
+ <translation>新しいパスフレーズ</translation>
</message>
<message>
<location line="+14"/>
<source>Repeat new passphrase</source>
- <translation>新しいのパスフレーズを繰り返して</translation>
+ <translation>新しいパスフレーズをもう一度</translation>
</message>
<message>
<location filename="../askpassphrasedialog.cpp" line="+33"/>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
- <translation>財布の新しいのパスフレーズを入って。&lt;br/&gt;&lt;b&gt;8個以上のワードか10個以上のランダムな文字&lt;/b&gt;を使ってください。</translation>
+ <translation>ウォレットの新しいパスフレーズを入力してください。&lt;br/&gt;&lt;b&gt;8個以上の単語か10個以上のランダムな文字&lt;/b&gt;を使ってください。</translation>
</message>
<message>
<location line="+1"/>
<source>Encrypt wallet</source>
- <translation>財布を暗号化する</translation>
+ <translation>ウォレットを暗号化する</translation>
</message>
<message>
<location line="+3"/>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>この動作は財布のアンロックするように財布のパスフレーズが必要です。</translation>
+ <translation>この操作はウォレットをアンロックするためにパスフレーズが必要です。</translation>
</message>
<message>
<location line="+5"/>
<source>Unlock wallet</source>
- <translation>財布をアンロックする</translation>
+ <translation>ウォレットをアンロックする</translation>
</message>
<message>
<location line="+3"/>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>この動作は財布の解読するように財布のパスフレーズが必要です。</translation>
+ <translation>この操作はウォレットの暗号化解除のためにパスフレーズが必要です。</translation>
</message>
<message>
<location line="+5"/>
<source>Decrypt wallet</source>
- <translation>財布を解読する</translation>
+ <translation>ウォレットの暗号化を解除する</translation>
</message>
<message>
<location line="+3"/>
<source>Change passphrase</source>
- <translation>パスフレーズを変わります</translation>
+ <translation>パスフレーズの変更</translation>
</message>
<message>
<location line="+1"/>
<source>Enter the old and new passphrase to the wallet.</source>
- <translation>前と新しいの財布のパスフレーズを入って。</translation>
+ <translation>新旧両方のパスフレーズを入力してください。</translation>
</message>
<message>
<location line="+46"/>
<source>Confirm wallet encryption</source>
- <translation>財布の暗号化を確認する</translation>
+ <translation>ウォレットの暗号化を確認する</translation>
</message>
<message>
<location line="+1"/>
@@ -266,7 +266,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<location line="-130"/>
<location line="+58"/>
<source>Wallet encrypted</source>
- <translation>財布は暗号化しました</translation>
+ <translation>ウォレットは暗号化されました</translation>
</message>
<message>
<location line="-56"/>
@@ -279,35 +279,35 @@ This product includes software developed by the OpenSSL Project for use in the O
<location line="+42"/>
<location line="+6"/>
<source>Wallet encryption failed</source>
- <translation>財布の暗号化するのは失敗しました</translation>
+ <translation>ウォレットの暗号化に失敗しました</translation>
</message>
<message>
<location line="-54"/>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>内部エラーですから財布の暗号化が失敗しました。財布は暗号化しませんでした。</translation>
+ <translation>内部エラーによりウォレットの暗号化が失敗しました。ウォレットは暗号化されませんでした。</translation>
</message>
<message>
<location line="+7"/>
<location line="+48"/>
<source>The supplied passphrases do not match.</source>
- <translation>パスフレーズは同じではありません。</translation>
+ <translation>パスフレーズが同じではありません。</translation>
</message>
<message>
<location line="-37"/>
<source>Wallet unlock failed</source>
- <translation>財布のアンロックは失敗しました</translation>
+ <translation>ウォレットのアンロックに失敗しました</translation>
</message>
<message>
<location line="+1"/>
<location line="+11"/>
<location line="+19"/>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>財布の</translation>
+ <translation>ウォレットの暗号化解除のパスフレーズが正しくありません。</translation>
</message>
<message>
<location line="-20"/>
<source>Wallet decryption failed</source>
- <translation>財布の解読は失敗しました</translation>
+ <translation>ウォレットの暗号化解除に失敗しました</translation>
</message>
<message>
<location line="+14"/>
@@ -325,37 +325,37 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+280"/>
<source>Synchronizing with network...</source>
- <translation>ネットワークと同期化中。。。</translation>
+ <translation>ネットワークに同期中……</translation>
</message>
<message>
<location line="-349"/>
<source>&amp;Overview</source>
- <translation>&amp;概観</translation>
+ <translation>概要(&amp;O)</translation>
</message>
<message>
<location line="+1"/>
<source>Show general overview of wallet</source>
- <translation>財布の概観を見せる</translation>
+ <translation>ウォレットの概要を見る</translation>
</message>
<message>
<location line="+20"/>
<source>&amp;Transactions</source>
- <translation>&amp;取引</translation>
+ <translation>取引(&amp;T)</translation>
</message>
<message>
<location line="+1"/>
<source>Browse transaction history</source>
- <translation>昔の取引をブラウズする</translation>
+ <translation>取引履歴を閲覧</translation>
</message>
<message>
<location line="+7"/>
<source>Edit the list of stored addresses and labels</source>
- <translation>アドレスとレーベルのリストを編集する</translation>
+ <translation>保存されたアドレスとラベルのリストを編集</translation>
</message>
<message>
<location line="-14"/>
<source>Show the list of addresses for receiving payments</source>
- <translation>支払いを受け取るのアドレスのリストを見せる</translation>
+ <translation>支払い受け取り用アドレスのリストを見る</translation>
</message>
<message>
<location line="+31"/>
@@ -365,12 +365,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+1"/>
<source>Quit application</source>
- <translation>アプリを終了</translation>
+ <translation>アプリケーションを終了</translation>
</message>
<message>
<location line="+4"/>
<source>Show information about Bitcoin</source>
- <translation>Bitcoinの事の情報を見せる</translation>
+ <translation>Bitcoinに関する情報を見る</translation>
</message>
<message>
<location line="+2"/>
@@ -385,7 +385,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+2"/>
<source>&amp;Options...</source>
- <translation>&amp;オプションズ</translation>
+ <translation>オプション(&amp;O)</translation>
</message>
<message>
<location line="+6"/>
@@ -430,7 +430,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+2"/>
<source>Change the passphrase used for wallet encryption</source>
- <translation>財布の暗号化のためのパスフレーズを変わる</translation>
+ <translation>ウォレット暗号化用パスフレーズの変更</translation>
</message>
<message>
<location line="+6"/>
@@ -506,17 +506,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+28"/>
<source>&amp;File</source>
- <translation>&amp;ファイル</translation>
+ <translation>ファイル(&amp;F)</translation>
</message>
<message>
<location line="+7"/>
<source>&amp;Settings</source>
- <translation>&amp;設定</translation>
+ <translation>設定(&amp;S)</translation>
</message>
<message>
<location line="+6"/>
<source>&amp;Help</source>
- <translation>&amp;ヘルプ</translation>
+ <translation>ヘルプ(&amp;H)</translation>
</message>
<message>
<location line="+9"/>
@@ -527,7 +527,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<location line="+17"/>
<location line="+10"/>
<source>[testnet]</source>
- <translation>[テストネット]</translation>
+ <translation>[testnet]</translation>
</message>
<message>
<location line="+47"/>
@@ -607,12 +607,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="-140"/>
<source>Up to date</source>
- <translation>新しいのバージョンが無し</translation>
+ <translation>バージョンは最新です</translation>
</message>
<message>
<location line="+31"/>
<source>Catching up...</source>
- <translation>追いつく中。。。</translation>
+ <translation type="unfinished"/>
</message>
<message>
<location line="+113"/>
@@ -622,12 +622,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+8"/>
<source>Sent transaction</source>
- <translation>送ったの取引</translation>
+ <translation>送金取引</translation>
</message>
<message>
<location line="+0"/>
<source>Incoming transaction</source>
- <translation>入ってくるの取引</translation>
+ <translation>着金取引</translation>
</message>
<message>
<location line="+1"/>
@@ -653,12 +653,12 @@ Address: %4
<message>
<location line="+17"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation>財布は&lt;b&gt;暗号化とアンロックです&lt;/b&gt;</translation>
+ <translation>ウォレットは&lt;b&gt;暗号化され、アンロックされています&lt;/b&gt;</translation>
</message>
<message>
<location line="+8"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>財布は&lt;b&gt;暗号化とロックです&lt;/b&gt;</translation>
+ <translation>ウォレットは&lt;b&gt;暗号化され、ロックされています&lt;/b&gt;</translation>
</message>
<message>
<location filename="../bitcoin.cpp" line="+111"/>
@@ -679,12 +679,12 @@ Address: %4
<message>
<location filename="../forms/editaddressdialog.ui" line="+14"/>
<source>Edit Address</source>
- <translation>アドレスを編集する</translation>
+ <translation>アドレスの編集</translation>
</message>
<message>
<location line="+11"/>
<source>&amp;Label</source>
- <translation>&amp;レーベル</translation>
+ <translation>ラベル(&amp;L)</translation>
</message>
<message>
<location line="+10"/>
@@ -1646,7 +1646,7 @@ Address: %4
<message>
<location line="+1"/>
<source>[testnet]</source>
- <translation type="unfinished"/>
+ <translation>[testnet]</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index f444d461f4..35b951614e 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -809,7 +809,7 @@ Inscriptio: %4
<message>
<location line="+6"/>
<source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source>
- <translation type="unfinished"/>
+ <translation>Optionalis merces transactionum singulis kB quae adiuvat curare tuas transactiones processas esse celeriter. Plurimi transactiones 1kB sunt.</translation>
</message>
<message>
<location line="+15"/>
@@ -2136,7 +2136,7 @@ Inscriptio: %4
<message>
<location filename="../walletmodel.cpp" line="+193"/>
<source>Send Coins</source>
- <translation type="unfinished"/>
+ <translation>Mitte Nummos</translation>
</message>
</context>
<context>
@@ -2144,7 +2144,7 @@ Inscriptio: %4
<message>
<location filename="../walletview.cpp" line="+42"/>
<source>&amp;Export</source>
- <translation type="unfinished"/>
+ <translation>&amp;Exporta</translation>
</message>
<message>
<location line="+1"/>
@@ -2517,7 +2517,7 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="+1"/>
<source>Generate coins (default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Genera nummos (praedefinitum: 0)</translation>
</message>
<message>
<location line="+2"/>
@@ -2532,7 +2532,7 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="+19"/>
<source>Not enough file descriptors available.</source>
- <translation type="unfinished"/>
+ <translation>Inopia descriptorum plicarum.</translation>
</message>
<message>
<location line="+8"/>
@@ -2562,7 +2562,7 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="-76"/>
<source>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</source>
- <translation type="unfinished"/>
+ <translation>Constitue numerum filorum verificationis scriptorum (Maximum 16, 0 = auto, &lt;0 = tot corda libera erunt, praedefinitum: 0)</translation>
</message>
<message>
<location line="+77"/>
@@ -2577,12 +2577,12 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="+1"/>
<source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Quantitas non valida pro -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Quantitas non valida pro -mintxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+8"/>
@@ -2662,7 +2662,7 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="+1"/>
<source>Signing transaction failed</source>
- <translation type="unfinished"/>
+ <translation>Signandum transactionis abortum est</translation>
</message>
<message>
<location line="+2"/>
@@ -2677,17 +2677,17 @@ exempli gratia: alertnotify=echo %%s | mail -s &quot;Bitcoin Notificatio&quot; a
<message>
<location line="+4"/>
<source>Transaction amount too small</source>
- <translation type="unfinished"/>
+ <translation>Magnitudo transactionis nimis parva</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction amounts must be positive</source>
- <translation type="unfinished"/>
+ <translation>Necesse est magnitudines transactionum positivas esse.</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction too large</source>
- <translation type="unfinished"/>
+ <translation>Transactio nimis magna</translation>
</message>
<message>
<location line="+7"/>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index 8a5850d312..4048cc0132 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -2578,12 +2578,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+1"/>
<source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Ongeldig bedrag voor -minrelaytxfee=&lt;bedrag&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Ongeldig bedrag voor -mintxfee=&lt;bedrag&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+8"/>
@@ -2663,7 +2663,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+1"/>
<source>Signing transaction failed</source>
- <translation type="unfinished"/>
+ <translation>Ondertekenen van transactie mislukt</translation>
</message>
<message>
<location line="+2"/>
@@ -2678,17 +2678,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+4"/>
<source>Transaction amount too small</source>
- <translation type="unfinished"/>
+ <translation>Transactiebedrag te klein</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction amounts must be positive</source>
- <translation type="unfinished"/>
+ <translation>Transactiebedragen moeten positief zijn</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction too large</source>
- <translation type="unfinished"/>
+ <translation>Transactie te groot</translation>
</message>
<message>
<location line="+7"/>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index fbf536e732..3399f7ad94 100644
--- a/src/qt/locale/bitcoin_pt_BR.ts
+++ b/src/qt/locale/bitcoin_pt_BR.ts
@@ -35,7 +35,7 @@ Este produto inclui software desenvolvido pelo Projeto OpenSSL para uso no OpenS
<message>
<location line="+0"/>
<source>The Bitcoin developers</source>
- <translation type="unfinished"/>
+ <translation>Desenvolvedores do Bitcoin</translation>
</message>
</context>
<context>
@@ -103,7 +103,7 @@ Este produto inclui software desenvolvido pelo Projeto OpenSSL para uso no OpenS
<message>
<location line="+3"/>
<source>&amp;Export</source>
- <translation type="unfinished"/>
+ <translation>&amp;Exportar</translation>
</message>
<message>
<location line="-44"/>
@@ -1649,7 +1649,7 @@ Endereço: %4</translation>
<message>
<location filename="../splashscreen.cpp" line="+22"/>
<source>The Bitcoin developers</source>
- <translation type="unfinished"/>
+ <translation>Desenvolvedores do Bitcoin</translation>
</message>
<message>
<location line="+1"/>
@@ -2144,7 +2144,7 @@ Endereço: %4</translation>
<message>
<location filename="../walletview.cpp" line="+42"/>
<source>&amp;Export</source>
- <translation type="unfinished"/>
+ <translation>&amp;Exportar</translation>
</message>
<message>
<location line="+1"/>
diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts
index 0aed1f4295..e2b6af5019 100644
--- a/src/qt/locale/bitcoin_pt_PT.ts
+++ b/src/qt/locale/bitcoin_pt_PT.ts
@@ -2578,12 +2578,12 @@ por exemplo: alertnotify=echo %%s | mail -s &quot;Alerta Bitcoin&quot; admin@foo
<message>
<location line="+1"/>
<source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Quantia inválida para -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+1"/>
<source>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <translation type="unfinished"/>
+ <translation>Quantia inválida para -mintxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
<location line="+8"/>
@@ -2663,7 +2663,7 @@ por exemplo: alertnotify=echo %%s | mail -s &quot;Alerta Bitcoin&quot; admin@foo
<message>
<location line="+1"/>
<source>Signing transaction failed</source>
- <translation type="unfinished"/>
+ <translation>Falhou assinatura da transação</translation>
</message>
<message>
<location line="+2"/>
@@ -2678,17 +2678,17 @@ por exemplo: alertnotify=echo %%s | mail -s &quot;Alerta Bitcoin&quot; admin@foo
<message>
<location line="+4"/>
<source>Transaction amount too small</source>
- <translation type="unfinished"/>
+ <translation>Quantia da transação é muito baixa</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction amounts must be positive</source>
- <translation type="unfinished"/>
+ <translation>Quantia da transação deverá ser positiva</translation>
</message>
<message>
<location line="+1"/>
<source>Transaction too large</source>
- <translation type="unfinished"/>
+ <translation>Transação grande demais</translation>
</message>
<message>
<location line="+7"/>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index cebdff0e02..72d8a8d57a 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -435,12 +435,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+6"/>
<source>&amp;Debug window</source>
- <translation type="unfinished"/>
+ <translation>&amp;Okno pre ladenie</translation>
</message>
<message>
<location line="+1"/>
<source>Open debugging and diagnostic console</source>
- <translation type="unfinished"/>
+ <translation>Otvor konzolu pre ladenie a diagnostiku</translation>
</message>
<message>
<location line="-4"/>
@@ -532,7 +532,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+47"/>
<source>Bitcoin client</source>
- <translation type="unfinished"/>
+ <translation>Bitcoin klient</translation>
</message>
<message numerus="yes">
<location line="+141"/>
@@ -617,7 +617,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<message>
<location line="+113"/>
<source>Confirm transaction fee</source>
- <translation type="unfinished"/>
+ <translation>Potvrď poplatok za transakciu.</translation>
</message>
<message>
<location line="+8"/>
@@ -1102,7 +1102,7 @@ Adresa: %4</translation>
<message>
<location filename="../qrcodedialog.cpp" line="+62"/>
<source>Error encoding URI into QR Code.</source>
- <translation type="unfinished"/>
+ <translation>Chyba v zakódovaní URI do QR kódu</translation>
</message>
<message>
<location line="+40"/>
@@ -1112,17 +1112,17 @@ Adresa: %4</translation>
<message>
<location line="+23"/>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation type="unfinished"/>
+ <translation>Výsledné URI príliš dlhé, skráť text pre názov / správu.</translation>
</message>
<message>
<location line="+25"/>
<source>Save QR Code</source>
- <translation type="unfinished"/>
+ <translation>Ukladanie QR kódu</translation>
</message>
<message>
<location line="+0"/>
<source>PNG Images (*.png)</source>
- <translation type="unfinished"/>
+ <translation>PNG obrázky (*.png)</translation>
</message>
</context>
<context>
@@ -1130,7 +1130,7 @@ Adresa: %4</translation>
<message>
<location filename="../forms/rpcconsole.ui" line="+46"/>
<source>Client name</source>
- <translation type="unfinished"/>
+ <translation>Meno klienta</translation>
</message>
<message>
<location line="+10"/>
@@ -1144,12 +1144,12 @@ Adresa: %4</translation>
<location line="+23"/>
<location filename="../rpcconsole.cpp" line="+339"/>
<source>N/A</source>
- <translation type="unfinished"/>
+ <translation>nie je k dispozícii</translation>
</message>
<message>
<location line="-217"/>
<source>Client version</source>
- <translation type="unfinished"/>
+ <translation>Verzia klienta</translation>
</message>
<message>
<location line="-45"/>
@@ -1169,27 +1169,27 @@ Adresa: %4</translation>
<message>
<location line="+29"/>
<source>Network</source>
- <translation type="unfinished"/>
+ <translation>Sieť</translation>
</message>
<message>
<location line="+7"/>
<source>Number of connections</source>
- <translation type="unfinished"/>
+ <translation>Počet pripojení</translation>
</message>
<message>
<location line="+23"/>
<source>On testnet</source>
- <translation type="unfinished"/>
+ <translation>Na testovacej sieti</translation>
</message>
<message>
<location line="+23"/>
<source>Block chain</source>
- <translation type="unfinished"/>
+ <translation>Reťazec blokov</translation>
</message>
<message>
<location line="+7"/>
<source>Current number of blocks</source>
- <translation type="unfinished"/>
+ <translation>Aktuálny počet blokov</translation>
</message>
<message>
<location line="+23"/>
@@ -2227,7 +2227,7 @@ Adresa: %4</translation>
<message>
<location line="-9"/>
<source>Set database cache size in megabytes (default: 25)</source>
- <translation type="unfinished"/>
+ <translation>Veľkosť vyrovnávajúcej pamäte pre databázu v megabytoch (predvolené:25)</translation>
</message>
<message>
<location line="-28"/>
@@ -2252,12 +2252,12 @@ Adresa: %4</translation>
<message>
<location line="+3"/>
<source>Threshold for disconnecting misbehaving peers (default: 100)</source>
- <translation type="unfinished"/>
+ <translation>Hranica pre odpojenie zle sa správajúcich peerov (predvolené: 100)</translation>
</message>
<message>
<location line="-134"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
- <translation type="unfinished"/>
+ <translation>Počet sekúnd kedy sa zabráni zle sa správajúcim peerom znovupripojenie (predvolené: 86400)</translation>
</message>
<message>
<location line="-29"/>
@@ -2732,12 +2732,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-120"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
- <translation type="unfinished"/>
+ <translation>Vykonaj príkaz, ak zmeny v najlepšom bloku (%s v príkaze nahradí blok hash)</translation>
</message>
<message>
<location line="+147"/>
<source>Upgrade wallet to latest format</source>
- <translation type="unfinished"/>
+ <translation>Aktualizuj peňaženku na najnovší formát.</translation>
</message>
<message>
<location line="-21"/>
@@ -2852,7 +2852,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-6"/>
<source>Insufficient funds</source>
- <translation type="unfinished"/>
+ <translation>Nedostatok prostriedkov</translation>
</message>
<message>
<location line="+10"/>
@@ -2862,7 +2862,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-57"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
- <translation>Pridať nódu a pripojiť sa and attempt to keep the connection open</translation>
+ <translation>Pridať nód na pripojenie a pokus o udržanie pripojenia otvoreného</translation>
</message>
<message>
<location line="-25"/>
@@ -2882,12 +2882,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="-52"/>
<source>Cannot downgrade wallet</source>
- <translation type="unfinished"/>
+ <translation>Nie je možné prejsť na nižšiu verziu peňaženky</translation>
</message>
<message>
<location line="+3"/>
<source>Cannot write default address</source>
- <translation type="unfinished"/>
+ <translation>Nie je možné zapísať predvolenú adresu.</translation>
</message>
<message>
<location line="+64"/>
@@ -2902,7 +2902,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<message>
<location line="+82"/>
<source>To use the %s option</source>
- <translation type="unfinished"/>
+ <translation>Použiť %s možnosť.</translation>
</message>
<message>
<location line="-74"/>
@@ -2914,7 +2914,9 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<source>You must set rpcpassword=&lt;password&gt; in the configuration file:
%s
If the file does not exist, create it with owner-readable-only file permissions.</source>
- <translation type="unfinished"/>
+ <translation>Musíš nastaviť rpcpassword=&lt;heslo&gt; v konfiguračnom súbore:
+%s
+Ak súbor neexistuje, vytvor ho s oprávnením pre čítanie len vlastníkom (owner-readable-only)</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index 94e642758e..1b4e6c76e7 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -2573,7 +2573,7 @@ alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
<message>
<location line="-76"/>
<source>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</source>
- <translation type="unfinished"/>
+ <translation>設定指令碼驗證的執行緒數目 (最多為 16, 若為 0 表示程式自動決定, 小於 0 表示保留不用的處理器核心數目, 預設為 0)</translation>
</message>
<message>
<location line="+77"/>
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index b6ea8e1d03..8f826941b2 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -2,8 +2,8 @@
#include <QMenu>
#include <QWidget>
-
-extern void qt_mac_set_dock_menu(QMenu*);
+#include <QTemporaryFile>
+#include <QImageWriter>
#undef slots
#include <Cocoa/Cocoa.h>
@@ -47,11 +47,12 @@ extern void qt_mac_set_dock_menu(QMenu*);
MacDockIconHandler::MacDockIconHandler() : QObject()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- this->m_dockIconClickEventHandler = [[DockIconClickEventHandler alloc] initWithDockIconHandler:this];
+ this->m_dockIconClickEventHandler = [[DockIconClickEventHandler alloc] initWithDockIconHandler:this];
this->m_dummyWidget = new QWidget();
this->m_dockMenu = new QMenu(this->m_dummyWidget);
- qt_mac_set_dock_menu(this->m_dockMenu);
+ this->setMainWindow(NULL);
+
[pool release];
}
@@ -74,15 +75,29 @@ QMenu *MacDockIconHandler::dockMenu()
void MacDockIconHandler::setIcon(const QIcon &icon)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSImage *image;
+ NSImage *image = nil;
if (icon.isNull())
image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
else {
+ // generate NSImage from QIcon and use this as dock icon.
QSize size = icon.actualSize(QSize(128, 128));
QPixmap pixmap = icon.pixmap(size);
- CGImageRef cgImage = pixmap.toMacCGImageRef();
- image = [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
- CFRelease(cgImage);
+
+ // write temp file hack (could also be done through QIODevice [memory])
+ QTemporaryFile notificationIconFile;
+ if (!pixmap.isNull() && notificationIconFile.open()) {
+ QImageWriter writer(&notificationIconFile, "PNG");
+ if (writer.write(pixmap.toImage())) {
+ const char *cString = notificationIconFile.fileName().toUtf8().data();
+ NSString *macString = [NSString stringWithCString:cString encoding:NSUTF8StringEncoding];
+ image = [[NSImage alloc] initWithContentsOfFile:macString];
+ }
+ }
+
+ if(!image) {
+ // if testnet image could not be created, load std. app icon
+ image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
+ }
}
[NSApp setApplicationIconImage:image];
@@ -100,8 +115,11 @@ MacDockIconHandler *MacDockIconHandler::instance()
void MacDockIconHandler::handleDockIconClickEvent()
{
- this->mainWindow->activateWindow();
- this->mainWindow->show();
+ if (this->mainWindow)
+ {
+ this->mainWindow->activateWindow();
+ this->mainWindow->show();
+ }
emit this->dockIconClicked();
}
diff --git a/src/qt/macnotificationhandler.h b/src/qt/macnotificationhandler.h
new file mode 100644
index 0000000000..cd8064c61c
--- /dev/null
+++ b/src/qt/macnotificationhandler.h
@@ -0,0 +1,25 @@
+#ifndef MACNOTIFICATIONHANDLER_H
+#define MACNOTIFICATIONHANDLER_H
+#include <QObject>
+
+/** Macintosh-specific notification handler (supports UserNotificationCenter and Growl).
+ */
+class MacNotificationHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ /** shows a 10.8+ UserNotification in the UserNotificationCenter
+ */
+ void showNotification(const QString &title, const QString &text);
+
+ /** executes AppleScript */
+ void sendAppleScript(const QString &script);
+
+ /** check if OS can handle UserNotifications */
+ bool hasUserNotificationCenterSupport(void);
+ static MacNotificationHandler *instance();
+};
+
+
+#endif // MACNOTIFICATIONHANDLER_H
diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm
new file mode 100644
index 0000000000..8bb9b887a1
--- /dev/null
+++ b/src/qt/macnotificationhandler.mm
@@ -0,0 +1,65 @@
+#include "macnotificationhandler.h"
+
+#undef slots
+#include <Cocoa/Cocoa.h>
+
+void MacNotificationHandler::showNotification(const QString &title, const QString &text)
+{
+ // check if users OS has support for NSUserNotification
+ if(this->hasUserNotificationCenterSupport()) {
+ // okay, seems like 10.8+
+ QByteArray utf8 = title.toUtf8();
+ char* cString = (char *)utf8.constData();
+ NSString *titleMac = [[NSString alloc] initWithUTF8String:cString];
+
+ utf8 = text.toUtf8();
+ cString = (char *)utf8.constData();
+ NSString *textMac = [[NSString alloc] initWithUTF8String:cString];
+
+ // do everything weak linked (because we will keep <10.8 compatibility)
+ id userNotification = [[NSClassFromString(@"NSUserNotification") alloc] init];
+ [userNotification performSelector:@selector(setTitle:) withObject:titleMac];
+ [userNotification performSelector:@selector(setInformativeText:) withObject:textMac];
+
+ id notificationCenterInstance = [NSClassFromString(@"NSUserNotificationCenter") performSelector:@selector(defaultUserNotificationCenter)];
+ [notificationCenterInstance performSelector:@selector(deliverNotification:) withObject:userNotification];
+
+ [titleMac release];
+ [textMac release];
+ [userNotification release];
+ }
+}
+
+// sendAppleScript just take a QString and executes it as apple script
+void MacNotificationHandler::sendAppleScript(const QString &script)
+{
+ QByteArray utf8 = script.toUtf8();
+ char* cString = (char *)utf8.constData();
+ NSString *scriptApple = [[NSString alloc] initWithUTF8String:cString];
+
+ NSAppleScript *as = [[NSAppleScript alloc] initWithSource:scriptApple];
+ NSDictionary *err = nil;
+ [as executeAndReturnError:&err];
+ [as release];
+ [scriptApple release];
+}
+
+bool MacNotificationHandler::hasUserNotificationCenterSupport(void)
+{
+ Class possibleClass = NSClassFromString(@"NSUserNotificationCenter");
+
+ // check if users OS has support for NSUserNotification
+ if(possibleClass!=nil) {
+ return true;
+ }
+ return false;
+}
+
+
+MacNotificationHandler *MacNotificationHandler::instance()
+{
+ static MacNotificationHandler *s_instance = NULL;
+ if (!s_instance)
+ s_instance = new MacNotificationHandler();
+ return s_instance;
+}
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index 397e7aa4a0..7cfaef6079 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -18,7 +18,7 @@
#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
-extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret);
+#include "macnotificationhandler.h"
#endif
// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
@@ -47,19 +47,25 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
}
#endif
#ifdef Q_OS_MAC
- // Check if Growl is installed (based on Qt's tray icon implementation)
- CFURLRef cfurl;
- OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
- if (status != kLSApplicationNotFoundErr) {
- CFBundleRef bundle = CFBundleCreate(0, cfurl);
- if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
- if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/")))
- mode = Growl13;
- else
- mode = Growl12;
+ // check if users OS has support for NSUserNotification
+ if( MacNotificationHandler::instance()->hasUserNotificationCenterSupport()) {
+ mode = UserNotificationCenter;
+ }
+ else {
+ // Check if Growl is installed (based on Qt's tray icon implementation)
+ CFURLRef cfurl;
+ OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
+ if (status != kLSApplicationNotFoundErr) {
+ CFBundleRef bundle = CFBundleCreate(0, cfurl);
+ if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
+ if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/")))
+ mode = Growl13;
+ else
+ mode = Growl12;
+ }
+ CFRelease(cfurl);
+ CFRelease(bundle);
}
- CFRelease(cfurl);
- CFRelease(bundle);
}
#endif
}
@@ -269,8 +275,14 @@ void Notificator::notifyGrowl(Class cls, const QString &title, const QString &te
quotedTitle.replace("\\", "\\\\").replace("\"", "\\");
quotedText.replace("\\", "\\\\").replace("\"", "\\");
QString growlApp(this->mode == Notificator::Growl13 ? "Growl" : "GrowlHelperApp");
- qt_mac_execute_apple_script(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp), 0);
+ MacNotificationHandler::instance()->sendAppleScript(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp));
+}
+
+void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
+ // icon is not supported by the user notification center yet. OSX will use the app icon.
+ MacNotificationHandler::instance()->showNotification(title, text);
}
+
#endif
void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
@@ -286,6 +298,9 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
notifySystray(cls, title, text, icon, millisTimeout);
break;
#ifdef Q_OS_MAC
+ case UserNotificationCenter:
+ notifyMacUserNotificationCenter(cls, title, text, icon);
+ break;
case Growl12:
case Growl13:
notifyGrowl(cls, title, text, icon);
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index d20673abb6..d1fe37fea5 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -46,11 +46,12 @@ public slots:
private:
QWidget *parent;
enum Mode {
- None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */
- Freedesktop, /**< Use DBus org.freedesktop.Notifications */
- QSystemTray, /**< Use QSystemTray::showMessage */
- Growl12, /**< Use the Growl 1.2 notification system (Mac only) */
- Growl13 /**< Use the Growl 1.3 notification system (Mac only) */
+ None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */
+ Freedesktop, /**< Use DBus org.freedesktop.Notifications */
+ QSystemTray, /**< Use QSystemTray::showMessage */
+ Growl12, /**< Use the Growl 1.2 notification system (Mac only) */
+ Growl13, /**< Use the Growl 1.3 notification system (Mac only) */
+ UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */
};
QString programName;
Mode mode;
@@ -63,6 +64,7 @@ private:
void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
#ifdef Q_OS_MAC
void notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon);
+ void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon);
#endif
};
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 4fa1f60922..b2451aea31 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -45,7 +45,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
/* Window elements init */
#ifdef Q_OS_MAC
- ui->tabWindow->setVisible(false);
+ /* remove Window tab on Mac */
+ ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
#endif
/* Display elements init */
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index ad2d682b7b..ddd8891335 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -140,6 +140,7 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance));
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance));
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
// for the non-mining users
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index a92e6fc329..0b0bce55bb 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -18,7 +18,9 @@
#include <QLocalServer>
#include <QLocalSocket>
#include <QStringList>
+#if QT_VERSION < 0x050000
#include <QUrl>
+#endif
using namespace boost;
diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp
index ca94975128..6ddcaaf5d9 100644
--- a/src/qt/qrcodedialog.cpp
+++ b/src/qt/qrcodedialog.cpp
@@ -7,7 +7,9 @@
#include "optionsmodel.h"
#include <QPixmap>
+#if QT_VERSION < 0x050000
#include <QUrl>
+#endif
#include <qrencode.h>
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 50f22b877a..ef72b17201 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -8,7 +8,9 @@
#include <QTime>
#include <QThread>
#include <QKeyEvent>
+#if QT_VERSION < 0x050000
#include <QUrl>
+#endif
#include <QScrollBar>
#include <openssl/crypto.h>
@@ -252,8 +254,11 @@ void RPCConsole::setClientModel(ClientModel *model)
this->clientModel = model;
if(model)
{
- // Subscribe to information, replies, messages, errors
+ // Keep up to date with client
+ setNumConnections(model->getNumConnections());
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
+
+ setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
// Provide initial values
@@ -262,7 +267,6 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->buildDate->setText(model->formatBuildDate());
ui->startupTime->setText(model->formatClientStartupTime());
- setNumConnections(model->getNumConnections());
ui->isTestNet->setChecked(model->isTestNet());
}
}
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index eb3ce48a6e..2c7bab2045 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -93,7 +93,11 @@ void SendCoinsDialog::on_sendButton_clicked()
QStringList formatted;
foreach(const SendCoinsRecipient &rcp, recipients)
{
+#if QT_VERSION < 0x050000
formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
+#else
+ formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), rcp.label.toHtmlEscaped(), rcp.address));
+#endif
}
fNewRecipientAllowed = false;
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 7c43e5839e..9118770f4c 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -218,8 +218,8 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
ss << strMessageMagic;
ss << ui->messageIn_VM->document()->toPlainText().toStdString();
- CKey key;
- if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
+ CPubKey pubkey;
+ if (!pubkey.RecoverCompact(Hash(ss.begin(), ss.end()), vchSig))
{
ui->signatureIn_VM->setValid(false);
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
@@ -227,7 +227,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
return;
}
- if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr))
+ if (!(CBitcoinAddress(pubkey.GetID()) == addr))
{
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index f8d16699ca..e400278123 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -3,6 +3,7 @@
#include "util.h"
#include <QPainter>
+#undef loop /* ugh, remove this when the #define loop is gone from util.h */
#include <QApplication>
SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) :
@@ -26,7 +27,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) :
// load the bitmap for writing some text over it
QPixmap newPixmap;
- if(GetBoolArg("-testnet")) {
+ if(GetBoolArg("-testnet", false)) {
newPixmap = QPixmap(":/images/splash_testnet");
}
else {
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index e4dbf9c0d9..aeef721ce5 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -12,7 +12,7 @@
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
{
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1);
@@ -186,7 +186,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
}
- int64 nTxFee = nDebit - wtx.GetValueOut();
+ int64 nTxFee = nDebit - GetValueOut(wtx);
if (nTxFee > 0)
strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
}
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 40a5f735cd..e954508769 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -89,7 +89,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
//
// Debit
//
- int64 nTxFee = nDebit - wtx.GetValueOut();
+ int64 nTxFee = nDebit - GetValueOut(wtx);
for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
@@ -162,7 +162,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = nBestHeight;
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
{
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 9240b71c71..a43e29c476 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -176,7 +176,11 @@ void TransactionView::setModel(WalletModel *model)
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23);
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Date, 120);
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Type, 120);
+#if QT_VERSION < 0x050000
transactionView->horizontalHeader()->setResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
+#else
+ transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
+#endif
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Amount, 100);
}
}
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 83e4255c9f..50c03ac62d 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -8,11 +8,9 @@
#include "bitcoingui.h"
#include "walletstack.h"
-#include <QVBoxLayout>
+#include <QHBoxLayout>
#include <QMessageBox>
-#include <stdio.h>
-
WalletFrame::WalletFrame(BitcoinGUI *_gui) :
QFrame(_gui),
gui(_gui),
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 3649185e8a..d7092f9879 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -17,8 +17,9 @@ class WalletStack;
class WalletFrame : public QFrame
{
Q_OBJECT
+
public:
- explicit WalletFrame(BitcoinGUI *_gui);
+ explicit WalletFrame(BitcoinGUI *_gui = 0);
~WalletFrame();
void setClientModel(ClientModel *clientModel);
diff --git a/src/qt/walletstack.h b/src/qt/walletstack.h
index ea4cc121d1..506d595c0f 100644
--- a/src/qt/walletstack.h
+++ b/src/qt/walletstack.h
@@ -40,6 +40,7 @@ QT_END_NAMESPACE
class WalletStack : public QStackedWidget
{
Q_OBJECT
+
public:
explicit WalletStack(QWidget *parent = 0);
~WalletStack();
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 6d44c174b7..277c056693 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -21,7 +21,11 @@
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QAction>
+#if QT_VERSION < 0x050000
#include <QDesktopServices>
+#else
+#include <QStandardPaths>
+#endif
#include <QFileDialog>
#include <QPushButton>
@@ -232,7 +236,11 @@ void WalletView::encryptWallet(bool status)
void WalletView::backupWallet()
{
+#if QT_VERSION < 0x050000
QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+#else
+ QString saveDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+#endif
QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
if (!filename.isEmpty()) {
if (!walletModel->backupWallet(filename)) {
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 11af1abf5d..3c24016fe3 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -65,8 +65,9 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
- if (blockindex->pnext)
- result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
+ CBlockIndex *pnext = blockindex->GetNextInMainChain();
+ if (pnext)
+ result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
return result;
}
@@ -143,20 +144,34 @@ Value getblockhash(const Array& params, bool fHelp)
Value getblock(const Array& params, bool fHelp)
{
- if (fHelp || params.size() != 1)
+ if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "getblock <hash>\n"
- "Returns details of a block with given block-hash.");
+ "getblock <hash> [verbose=true]\n"
+ "If verbose is false, returns a string that is serialized, hex-encoded data for block <hash>.\n"
+ "If verbose is true, returns an Object with information about block <hash>."
+ );
std::string strHash = params[0].get_str();
uint256 hash(strHash);
+ bool fVerbose = true;
+ if (params.size() > 1)
+ fVerbose = params[1].get_bool();
+
if (mapBlockIndex.count(hash) == 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash];
- block.ReadFromDisk(pblockindex);
+ ReadBlockFromDisk(block, pblockindex);
+
+ if (!fVerbose)
+ {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ ssBlock << block;
+ std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
+ return strHex;
+ }
return blockToJSON(block, pblockindex);
}
@@ -228,4 +243,20 @@ Value gettxout(const Array& params, bool fHelp)
return ret;
}
+Value verifychain(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2)
+ throw runtime_error(
+ "verifychain [check level] [num blocks]\n"
+ "Verifies blockchain database.");
+
+ int nCheckLevel = GetArg("-checklevel", 3);
+ int nCheckDepth = GetArg("-checkblocks", 288);
+ if (params.size() > 0)
+ nCheckLevel = params[0].get_int();
+ if (params.size() > 1)
+ nCheckDepth = params[1].get_int();
+
+ return VerifyDB(nCheckLevel, nCheckDepth);
+}
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index 77cef02736..dcfb023f35 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -2,35 +2,68 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <iostream>
+#include <fstream>
+
#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
#include "ui_interface.h"
#include "base58.h"
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/variant/get.hpp>
+#include <boost/algorithm/string.hpp>
#define printf OutputDebugStringF
using namespace json_spirit;
using namespace std;
-class CTxDump
-{
-public:
- CBlockIndex *pindex;
- int64 nValue;
- bool fSpent;
- CWalletTx* ptx;
- int nOut;
- CTxDump(CWalletTx* ptx = NULL, int nOut = -1)
- {
- pindex = NULL;
- nValue = 0;
- fSpent = false;
- this->ptx = ptx;
- this->nOut = nOut;
+void EnsureWalletIsUnlocked();
+
+std::string static EncodeDumpTime(int64 nTime) {
+ return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
+}
+
+int64 static DecodeDumpTime(const std::string &str) {
+ static const boost::posix_time::time_input_facet facet("%Y-%m-%dT%H:%M:%SZ");
+ static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
+ const std::locale loc(std::locale::classic(), &facet);
+ std::istringstream iss(str);
+ iss.imbue(loc);
+ boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
+ iss >> ptime;
+ if (ptime.is_not_a_date_time())
+ return 0;
+ return (ptime - epoch).total_seconds();
+}
+
+std::string static EncodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ BOOST_FOREACH(unsigned char c, str) {
+ if (c <= 32 || c >= 128 || c == '%') {
+ ret << '%' << HexStr(&c, &c + 1);
+ } else {
+ ret << c;
+ }
+ }
+ return ret.str();
+}
+
+std::string DecodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ for (unsigned int pos = 0; pos < str.length(); pos++) {
+ unsigned char c = str[pos];
+ if (c == '%' && pos+2 < str.length()) {
+ c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
+ ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
+ pos += 2;
+ }
+ ret << c;
}
-};
+ return ret.str();
+}
Value importprivkey(const Array& params, bool fHelp)
{
@@ -54,20 +87,22 @@ Value importprivkey(const Array& params, bool fHelp)
if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
- CKey key;
- bool fCompressed;
- CSecret secret = vchSecret.GetSecret(fCompressed);
- key.SetSecret(secret, fCompressed);
- CKeyID vchAddress = key.GetPubKey().GetID();
+ CKey key = vchSecret.GetKey();
+ CPubKey pubkey = key.GetPubKey();
+ CKeyID vchAddress = pubkey.GetID();
{
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->MarkDirty();
pwalletMain->SetAddressBookName(vchAddress, strLabel);
- if (!pwalletMain->AddKey(key))
+ // Don't throw error in case a key is already there
+ if (pwalletMain->HaveKey(vchAddress))
+ return Value::null;
+
+ if (!pwalletMain->AddKeyPubKey(key, pubkey))
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
-
+
if (fRescan) {
pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
pwalletMain->ReacceptWalletTransactions();
@@ -77,6 +112,86 @@ Value importprivkey(const Array& params, bool fHelp)
return Value::null;
}
+Value importwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "importwallet <filename>\n"
+ "Imports keys from a wallet dump file (see dumpwallet).");
+
+ EnsureWalletIsUnlocked();
+
+ ifstream file;
+ file.open(params[0].get_str().c_str());
+ if (!file.is_open())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
+
+ int64 nTimeBegin = pindexBest->nTime;
+
+ bool fGood = true;
+
+ while (file.good()) {
+ std::string line;
+ std::getline(file, line);
+ if (line.empty() || line[0] == '#')
+ continue;
+
+ std::vector<std::string> vstr;
+ boost::split(vstr, line, boost::is_any_of(" "));
+ if (vstr.size() < 2)
+ continue;
+ CBitcoinSecret vchSecret;
+ if (!vchSecret.SetString(vstr[0]))
+ continue;
+ CKey key = vchSecret.GetKey();
+ CPubKey pubkey = key.GetPubKey();
+ CKeyID keyid = pubkey.GetID();
+ if (pwalletMain->HaveKey(keyid)) {
+ printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
+ continue;
+ }
+ int64 nTime = DecodeDumpTime(vstr[1]);
+ std::string strLabel;
+ bool fLabel = true;
+ for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
+ if (boost::algorithm::starts_with(vstr[nStr], "#"))
+ break;
+ if (vstr[nStr] == "change=1")
+ fLabel = false;
+ if (vstr[nStr] == "reserve=1")
+ fLabel = false;
+ if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
+ strLabel = DecodeDumpString(vstr[nStr].substr(6));
+ fLabel = true;
+ }
+ }
+ printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
+ if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
+ fGood = false;
+ continue;
+ }
+ pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
+ if (fLabel)
+ pwalletMain->SetAddressBookName(keyid, strLabel);
+ nTimeBegin = std::min(nTimeBegin, nTime);
+ }
+ file.close();
+
+ CBlockIndex *pindex = pindexBest;
+ while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
+ pindex = pindex->pprev;
+
+ printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
+ pwalletMain->ScanForWalletTransactions(pindex);
+ pwalletMain->ReacceptWalletTransactions();
+ pwalletMain->MarkDirty();
+
+ if (!fGood)
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
+
+ return Value::null;
+}
+
Value dumpprivkey(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -84,6 +199,8 @@ Value dumpprivkey(const Array& params, bool fHelp)
"dumpprivkey <bitcoinaddress>\n"
"Reveals the private key corresponding to <bitcoinaddress>.");
+ EnsureWalletIsUnlocked();
+
string strAddress = params[0].get_str();
CBitcoinAddress address;
if (!address.SetString(strAddress))
@@ -91,9 +208,63 @@ Value dumpprivkey(const Array& params, bool fHelp)
CKeyID keyID;
if (!address.GetKeyID(keyID))
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
- CSecret vchSecret;
- bool fCompressed;
- if (!pwalletMain->GetSecret(keyID, vchSecret, fCompressed))
+ CKey vchSecret;
+ if (!pwalletMain->GetKey(keyID, vchSecret))
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
- return CBitcoinSecret(vchSecret, fCompressed).ToString();
+ return CBitcoinSecret(vchSecret).ToString();
+}
+
+
+Value dumpwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "dumpwallet <filename>\n"
+ "Dumps all wallet keys in a human-readable format.");
+
+ EnsureWalletIsUnlocked();
+
+ ofstream file;
+ file.open(params[0].get_str().c_str());
+ if (!file.is_open())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
+
+ std::map<CKeyID, int64> mapKeyBirth;
+ std::set<CKeyID> setKeyPool;
+ pwalletMain->GetKeyBirthTimes(mapKeyBirth);
+ pwalletMain->GetAllReserveKeys(setKeyPool);
+
+ // sort time/key pairs
+ std::vector<std::pair<int64, CKeyID> > vKeyBirth;
+ for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
+ vKeyBirth.push_back(std::make_pair(it->second, it->first));
+ }
+ mapKeyBirth.clear();
+ std::sort(vKeyBirth.begin(), vKeyBirth.end());
+
+ // produce output
+ file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
+ file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
+ file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+ file << "\n";
+ for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
+ const CKeyID &keyid = it->second;
+ std::string strTime = EncodeDumpTime(it->first);
+ std::string strAddr = CBitcoinAddress(keyid).ToString();
+ CKey key;
+ if (pwalletMain->GetKey(keyid, key)) {
+ if (pwalletMain->mapAddressBook.count(keyid)) {
+ file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), EncodeDumpString(pwalletMain->mapAddressBook[keyid]).c_str(), strAddr.c_str());
+ } else if (setKeyPool.count(keyid)) {
+ file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), strAddr.c_str());
+ } else {
+ file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), strAddr.c_str());
+ }
+ }
+ }
+ file << "\n";
+ file << "# End of dump\n";
+ file.close();
+ return Value::null;
}
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index fddda8b5f4..a70c0958df 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "main.h"
+#include "chainparams.h"
#include "db.h"
#include "init.h"
#include "bitcoinrpc.h"
@@ -11,6 +11,21 @@
using namespace json_spirit;
using namespace std;
+// Key used by getwork/getblocktemplate miners.
+// Allocated in InitRPCMining, free'd in ShutdownRPCMining
+static CReserveKey* pMiningKey = NULL;
+
+void InitRPCMining()
+{
+ // getwork/getblocktemplate mining rewards paid here:
+ pMiningKey = new CReserveKey(pwalletMain);
+}
+
+void ShutdownRPCMining()
+{
+ delete pMiningKey; pMiningKey = NULL;
+}
+
Value getgenerate(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -18,7 +33,7 @@ Value getgenerate(const Array& params, bool fHelp)
"getgenerate\n"
"Returns true or false.");
- return GetBoolArg("-gen");
+ return GetBoolArg("-gen", false);
}
@@ -69,16 +84,16 @@ Value getmininginfo(const Array& params, bool fHelp)
"Returns an object containing mining-related information.");
Object obj;
- obj.push_back(Pair("blocks", (int)nBestHeight));
- obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
- obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("errors", GetWarnings("statusbar")));
- obj.push_back(Pair("generate", GetBoolArg("-gen")));
- obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
- obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
- obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
- obj.push_back(Pair("testnet", fTestNet));
+ obj.push_back(Pair("blocks", (int)nBestHeight));
+ obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
+ obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
+ obj.push_back(Pair("difficulty", (double)GetDifficulty()));
+ obj.push_back(Pair("errors", GetWarnings("statusbar")));
+ obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
+ obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
+ obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
+ obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
+ obj.push_back(Pair("testnet", TestNet()));
return obj;
}
@@ -104,7 +119,6 @@ Value getwork(const Array& params, bool fHelp)
typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
static mapNewBlock_t mapNewBlock; // FIXME: thread safety
static vector<CBlockTemplate*> vNewBlockTemplate;
- static CReserveKey reservekey(pwalletMain);
if (params.size() == 0)
{
@@ -134,7 +148,7 @@ Value getwork(const Array& params, bool fHelp)
nStart = GetTime();
// Create new block
- pblocktemplate = CreateNewBlock(reservekey);
+ pblocktemplate = CreateNewBlock(*pMiningKey);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
vNewBlockTemplate.push_back(pblocktemplate);
@@ -145,7 +159,7 @@ Value getwork(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
- pblock->UpdateTime(pindexPrev);
+ UpdateTime(*pblock, pindexPrev);
pblock->nNonce = 0;
// Update nExtraNonce
@@ -192,7 +206,7 @@ Value getwork(const Array& params, bool fHelp)
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
- return CheckWork(pblock, *pwalletMain, reservekey);
+ return CheckWork(pblock, *pwalletMain, *pMiningKey);
}
}
@@ -243,8 +257,6 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
- static CReserveKey reservekey(pwalletMain);
-
// Update block
static unsigned int nTransactionsUpdatedLast;
static CBlockIndex* pindexPrev;
@@ -267,7 +279,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
delete pblocktemplate;
pblocktemplate = NULL;
}
- pblocktemplate = CreateNewBlock(reservekey);
+ pblocktemplate = CreateNewBlock(*pMiningKey);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@@ -277,7 +289,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
- pblock->UpdateTime(pindexPrev);
+ UpdateTime(*pblock, pindexPrev);
pblock->nNonce = 0;
Array transactions;
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 644c2675ae..bd7bc0ba10 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -157,7 +157,7 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
BOOST_FOREACH(string& strAddNode, laddedNodes)
{
vector<CService> vservNode(0);
- if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
+ if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
laddedAddreses.push_back(make_pair(strAddNode, vservNode));
else
{
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index fb9811b921..f08688d386 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -9,7 +9,6 @@
#include "bitcoinrpc.h"
#include "db.h"
#include "init.h"
-#include "main.h"
#include "net.h"
#include "wallet.h"
@@ -407,10 +406,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
- CKey key;
- bool fCompressed;
- CSecret secret = vchSecret.GetSecret(fCompressed);
- key.SetSecret(secret, fCompressed);
+ CKey key = vchSecret.GetKey();
tempKeystore.AddKey(key);
}
}
@@ -558,7 +554,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
if (!fHave) {
// push to local node
CValidationState state;
- if (!tx.AcceptToMemoryPool(state, true, false))
+ if (!mempool.accept(state, tx, false, NULL))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state
}
}
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 5fd400c6bb..5388bd4d84 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -79,12 +79,12 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", fTestNet));
+ obj.push_back(Pair("testnet", TestNet()));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
if (pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
+ obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
}
@@ -374,11 +374,11 @@ Value verifymessage(const Array& params, bool fHelp)
ss << strMessageMagic;
ss << strMessage;
- CKey key;
- if (!key.SetCompactSignature(ss.GetHash(), vchSig))
+ CPubKey pubkey;
+ if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
return false;
- return (key.GetPubKey().GetID() == keyID);
+ return (pubkey.GetID() == keyID);
}
@@ -408,7 +408,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -454,7 +454,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
@@ -478,7 +478,7 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
- if (!wtx.IsFinal())
+ if (!IsFinalTx(wtx))
continue;
int64 nReceived, nSent, nFee;
@@ -719,7 +719,7 @@ static CScript _createmultisig(const Array& params)
throw runtime_error(
strprintf("not enough keys supplied "
"(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired));
- std::vector<CKey> pubkeys;
+ std::vector<CPubKey> pubkeys;
pubkeys.resize(keys.size());
for (unsigned int i = 0; i < keys.size(); i++)
{
@@ -737,16 +737,18 @@ static CScript _createmultisig(const Array& params)
if (!pwalletMain->GetPubKey(keyID, vchPubKey))
throw runtime_error(
strprintf("no full public key for address %s",ks.c_str()));
- if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+ if (!vchPubKey.IsFullyValid())
throw runtime_error(" Invalid public key: "+ks);
+ pubkeys[i] = vchPubKey;
}
// Case 2: hex public key
else if (IsHex(ks))
{
CPubKey vchPubKey(ParseHex(ks));
- if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
+ if (!vchPubKey.IsFullyValid())
throw runtime_error(" Invalid public key: "+ks);
+ pubkeys[i] = vchPubKey;
}
else
{
@@ -811,6 +813,7 @@ struct tallyitem
{
int64 nAmount;
int nConf;
+ vector<uint256> txids;
tallyitem()
{
nAmount = 0;
@@ -836,7 +839,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
+ if (wtx.IsCoinBase() || !IsFinalTx(wtx))
continue;
int nDepth = wtx.GetDepthInMainChain();
@@ -852,6 +855,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
tallyitem& item = mapTally[address];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
+ item.txids.push_back(wtx.GetHash());
}
}
@@ -887,6 +891,15 @@ Value ListReceived(const Array& params, bool fByAccounts)
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
+ Array transactions;
+ if (it != mapTally.end())
+ {
+ BOOST_FOREACH(const uint256& item, (*it).second.txids)
+ {
+ transactions.push_back(item.GetHex());
+ }
+ }
+ obj.push_back(Pair("txids", transactions));
ret.push_back(obj);
}
}
@@ -919,7 +932,8 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
" \"address\" : receiving address\n"
" \"account\" : the account of the receiving address\n"
" \"amount\" : total amount received by the address\n"
- " \"confirmations\" : number of confirmations of the most recent transaction included");
+ " \"confirmations\" : number of confirmations of the most recent transaction included\n"
+ " \"txids\" : list of transactions with outputs to the address\n");
return ListReceived(params, false);
}
@@ -1206,7 +1220,7 @@ Value gettransaction(const Array& params, bool fHelp)
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+ int64 nFee = (wtx.IsFromMe() ? GetValueOut(wtx) - nDebit : 0);
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
if (wtx.IsFromMe())
@@ -1256,56 +1270,11 @@ Value keypoolrefill(const Array& params, bool fHelp)
}
-void ThreadTopUpKeyPool(void* parg)
-{
- // Make this thread recognisable as the key-topping-up thread
- RenameThread("bitcoin-key-top");
-
- pwalletMain->TopUpKeyPool();
-}
-
-void ThreadCleanWalletPassphrase(void* parg)
+static void LockWallet(CWallet* pWallet)
{
- // Make this thread recognisable as the wallet relocking thread
- RenameThread("bitcoin-lock-wa");
-
- int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
-
- ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- if (nWalletUnlockTime == 0)
- {
- nWalletUnlockTime = nMyWakeTime;
-
- do
- {
- if (nWalletUnlockTime==0)
- break;
- int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
- if (nToSleep <= 0)
- break;
-
- LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
- MilliSleep(nToSleep);
- ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- } while(1);
-
- if (nWalletUnlockTime)
- {
- nWalletUnlockTime = 0;
- pwalletMain->Lock();
- }
- }
- else
- {
- if (nWalletUnlockTime < nMyWakeTime)
- nWalletUnlockTime = nMyWakeTime;
- }
-
- LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
-
- delete (int64*)parg;
+ LOCK(cs_nWalletUnlockTime);
+ nWalletUnlockTime = 0;
+ pWallet->Lock();
}
Value walletpassphrase(const Array& params, bool fHelp)
@@ -1319,9 +1288,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
if (!pwalletMain->IsCrypted())
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
- if (!pwalletMain->IsLocked())
- throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked.");
-
// Note that the walletpassphrase is stored in params[0] which is not mlock()ed
SecureString strWalletPass;
strWalletPass.reserve(100);
@@ -1339,9 +1305,12 @@ Value walletpassphrase(const Array& params, bool fHelp)
"walletpassphrase <passphrase> <timeout>\n"
"Stores the wallet decryption key in memory for <timeout> seconds.");
- NewThread(ThreadTopUpKeyPool, NULL);
- int64* pnSleepTime = new int64(params[1].get_int64());
- NewThread(ThreadCleanWalletPassphrase, pnSleepTime);
+ pwalletMain->TopUpKeyPool();
+
+ int64 nSleepTime = params[1].get_int64();
+ LOCK(cs_nWalletUnlockTime);
+ nWalletUnlockTime = GetTime() + nSleepTime;
+ RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
return Value::null;
}
@@ -1445,7 +1414,7 @@ public:
CPubKey vchPubKey;
pwalletMain->GetPubKey(keyID, vchPubKey);
obj.push_back(Pair("isscript", false));
- obj.push_back(Pair("pubkey", HexStr(vchPubKey.Raw())));
+ obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
return obj;
}
diff --git a/src/script.cpp b/src/script.cpp
index 90066efd33..14fe80e207 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -9,14 +9,14 @@ using namespace std;
using namespace boost;
#include "script.h"
+#include "core.h"
#include "keystore.h"
#include "bignum.h"
#include "key.h"
-#include "main.h"
#include "sync.h"
#include "util.h"
-bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
+bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
@@ -1033,13 +1033,13 @@ class CSignatureCache
{
private:
// sigdata_type is (signature hash, signature, public key):
- typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
+ typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
std::set< sigdata_type> setValid;
boost::shared_mutex cs_sigcache;
public:
bool
- Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
+ Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
@@ -1050,7 +1050,7 @@ public:
return false;
}
- void Set(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
+ void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
// DoS prevention: limit cache size to less than 10MB
// (~200 bytes per cache entry times 50,000 entries)
@@ -1081,11 +1081,15 @@ public:
}
};
-bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
+bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode,
const CTransaction& txTo, unsigned int nIn, int nHashType, int flags)
{
static CSignatureCache signatureCache;
+ CPubKey pubkey(vchPubKey);
+ if (!pubkey.IsValid())
+ return false;
+
// Hash type is one byte tacked on to the end of the signature
if (vchSig.empty())
return false;
@@ -1097,18 +1101,14 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType);
- if (signatureCache.Get(sighash, vchSig, vchPubKey))
+ if (signatureCache.Get(sighash, vchSig, pubkey))
return true;
- CKey key;
- if (!key.SetPubKey(vchPubKey))
- return false;
-
- if (!key.Verify(sighash, vchSig))
+ if (!pubkey.Verify(sighash, vchSig))
return false;
if (!(flags & SCRIPT_VERIFY_NOCACHE))
- signatureCache.Set(sighash, vchSig, vchPubKey);
+ signatureCache.Set(sighash, vchSig, pubkey);
return true;
}
@@ -1474,6 +1474,42 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto
return true;
}
+class CAffectedKeysVisitor : public boost::static_visitor<void> {
+private:
+ const CKeyStore &keystore;
+ std::vector<CKeyID> &vKeys;
+
+public:
+ CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+
+ void Process(const CScript &script) {
+ txnouttype type;
+ std::vector<CTxDestination> vDest;
+ int nRequired;
+ if (ExtractDestinations(script, type, vDest, nRequired)) {
+ BOOST_FOREACH(const CTxDestination &dest, vDest)
+ boost::apply_visitor(*this, dest);
+ }
+ }
+
+ void operator()(const CKeyID &keyId) {
+ if (keystore.HaveKey(keyId))
+ vKeys.push_back(keyId);
+ }
+
+ void operator()(const CScriptID &scriptId) {
+ CScript script;
+ if (keystore.GetCScript(scriptId, script))
+ Process(script);
+ }
+
+ void operator()(const CNoDestination &none) {}
+};
+
+void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys) {
+ CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey);
+}
+
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
unsigned int flags, int nHashType)
{
@@ -1770,13 +1806,13 @@ void CScript::SetDestination(const CTxDestination& dest)
boost::apply_visitor(CScriptVisitor(this), dest);
}
-void CScript::SetMultisig(int nRequired, const std::vector<CKey>& keys)
+void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
{
this->clear();
*this << EncodeOP_N(nRequired);
- BOOST_FOREACH(const CKey& key, keys)
- *this << key.GetPubKey();
+ BOOST_FOREACH(const CPubKey& key, keys)
+ *this << key;
*this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
}
@@ -1801,20 +1837,17 @@ bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
return false;
}
-bool CScriptCompressor::IsToPubKey(std::vector<unsigned char> &pubkey) const
+bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
{
if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
&& (script[1] == 0x02 || script[1] == 0x03)) {
- pubkey.resize(33);
- memcpy(&pubkey[0], &script[1], 33);
+ pubkey.Set(&script[1], &script[34]);
return true;
}
if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG
&& script[1] == 0x04) {
- pubkey.resize(65);
- memcpy(&pubkey[0], &script[1], 65);
- CKey key;
- return (key.SetPubKey(CPubKey(pubkey))); // SetPubKey fails if this is not a valid public key, a case that would not be compressible
+ pubkey.Set(&script[1], &script[66]);
+ return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
}
return false;
}
@@ -1835,7 +1868,7 @@ bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
memcpy(&out[1], &scriptID, 20);
return true;
}
- std::vector<unsigned char> pubkey;
+ CPubKey pubkey;
if (IsToPubKey(pubkey)) {
out.resize(33);
memcpy(&out[1], &pubkey[1], 32);
@@ -1888,17 +1921,16 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
return true;
case 0x04:
case 0x05:
- std::vector<unsigned char> vch(33, 0x00);
+ unsigned char vch[33] = {};
vch[0] = nSize - 2;
memcpy(&vch[1], &in[0], 32);
- CKey key;
- if (!key.SetPubKey(CPubKey(vch)))
+ CPubKey pubkey(&vch[0], &vch[33]);
+ if (!pubkey.Decompress())
return false;
- key.SetCompressedPubKey(false); // Decompress public key
- CPubKey pubkey = key.GetPubKey();
+ assert(pubkey.size() == 65);
script.resize(67);
script[0] = 65;
- memcpy(&script[1], &pubkey.Raw()[0], 65);
+ memcpy(&script[1], pubkey.begin(), 65);
script[66] = OP_CHECKSIG;
return true;
}
diff --git a/src/script.h b/src/script.h
index 4b29f6273c..03afe8b652 100644
--- a/src/script.h
+++ b/src/script.h
@@ -348,8 +348,10 @@ public:
CScript& operator<<(const CPubKey& key)
{
- std::vector<unsigned char> vchKey = key.Raw();
- return (*this) << vchKey;
+ assert(key.size() < OP_PUSHDATA1);
+ insert(end(), (unsigned char)key.size());
+ insert(end(), key.begin(), key.end());
+ return *this;
}
CScript& operator<<(const CBigNum& b)
@@ -531,7 +533,7 @@ public:
bool IsPayToScriptHash() const;
- // Called by CTransaction::IsStandard
+ // Called by IsStandardTx
bool IsPushOnly() const
{
const_iterator pc = begin();
@@ -548,7 +550,7 @@ public:
void SetDestination(const CTxDestination& address);
- void SetMultisig(int nRequired, const std::vector<CKey>& keys);
+ void SetMultisig(int nRequired, const std::vector<CPubKey>& keys);
void PrintHex() const
@@ -619,7 +621,7 @@ protected:
// form).
bool IsToKeyID(CKeyID &hash) const;
bool IsToScriptID(CScriptID &hash) const;
- bool IsToPubKey(std::vector<unsigned char> &pubkey) const;
+ bool IsToPubKey(CPubKey &pubkey) const;
bool Compress(std::vector<unsigned char> &out) const;
unsigned int GetSpecialSize(unsigned int nSize) const;
@@ -672,6 +674,7 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned c
bool IsStandard(const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
+void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index b1e98f65ed..ea0cc1bcef 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -8,6 +8,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
+#include "chainparams.h"
#include "main.h"
#include "wallet.h"
#include "net.h"
@@ -25,7 +26,7 @@ CService ip(uint32_t i)
{
struct in_addr s;
s.s_addr = i;
- return CService(CNetAddr(s), GetDefaultPort());
+ return CService(CNetAddr(s), Params().GetDefaultPort());
}
BOOST_AUTO_TEST_SUITE(DoS_tests)
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 7602fa93a6..af65416485 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -108,8 +108,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
- // Save global state
- bool fTestNet_stored = fTestNet;
BOOST_FOREACH(Value& tv, tests)
{
@@ -125,7 +123,10 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
const Object &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
- fTestNet = isTestnet; // Override testnet flag
+ if (isTestnet)
+ SelectParams(CChainParams::TESTNET);
+ else
+ SelectParams(CChainParams::MAIN);
if(isPrivkey)
{
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
@@ -133,9 +134,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
// Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
- bool fCompressedOut = false;
- CSecret privkey = secret.GetSecret(fCompressedOut);
- BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest);
+ CKey privkey = secret.GetKey();
+ BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
// Private key must be invalid public key
@@ -157,8 +157,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
}
}
- // Restore global state
- fTestNet = fTestNet_stored;
+ SelectParams(CChainParams::MAIN);
}
// Goal: check that generated keys match test vectors
@@ -166,9 +165,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
Array tests = read_json("base58_keys_valid.json");
std::vector<unsigned char> result;
- // Save global state
- bool fTestNet_stored = fTestNet;
-
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -183,12 +179,18 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
const Object &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
- fTestNet = isTestnet; // Override testnet flag
+ if (isTestnet)
+ SelectParams(CChainParams::TESTNET);
+ else
+ SelectParams(CChainParams::MAIN);
if(isPrivkey)
{
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ CKey key;
+ key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
+ assert(key.IsValid());
CBitcoinSecret secret;
- secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed);
+ secret.SetKey(key);
BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
}
else
@@ -223,8 +225,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
CTxDestination nodest = CNoDestination();
BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest));
- // Restore global state
- fTestNet = fTestNet_stored;
+ SelectParams(CChainParams::MAIN);
}
// Goal: check that base58 parsing code is robust against a variety of corrupted data
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 4a2851cf46..0d349a990c 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -73,14 +73,13 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
CBitcoinSecret vchSecret;
BOOST_CHECK(vchSecret.SetString(strSecret));
- CKey key;
- bool fCompressed;
- CSecret secret = vchSecret.GetSecret(fCompressed);
- key.SetSecret(secret, fCompressed);
+ CKey key = vchSecret.GetKey();
+ CPubKey pubkey = key.GetPubKey();
+ vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());
CBloomFilter filter(2, 0.001, 0, BLOOM_UPDATE_ALL);
- filter.insert(key.GetPubKey().Raw());
- uint160 hash = key.GetPubKey().GetID();
+ filter.insert(vchPubKey);
+ uint160 hash = pubkey.GetID();
filter.insert(vector<unsigned char>(hash.begin(), hash.end()));
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
index 3cfb6dbfa4..5675c40e76 100644
--- a/src/test/checkblock_tests.cpp
+++ b/src/test/checkblock_tests.cpp
@@ -52,12 +52,10 @@ BOOST_AUTO_TEST_CASE(May15)
if (read_block("Mar12Fork.dat", forkingBlock))
{
CValidationState state;
- forkingBlock.nTime = tMay15-1; // Invalidates PoW
- BOOST_CHECK(!forkingBlock.CheckBlock(state, false, false));
// After May 15'th, big blocks are OK:
forkingBlock.nTime = tMay15; // Invalidates PoW
- BOOST_CHECK(forkingBlock.CheckBlock(state, false, false));
+ BOOST_CHECK(CheckBlock(forkingBlock, state, false, false));
}
SetMockTime(0);
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index f01ee06cfa..a26f4a87db 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -23,7 +23,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true],
-["Tests for CTransaction::CheckTransaction()"],
+["Tests for CheckTransaction()"],
["No inputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"0100000000010000000000000000015100000000", true],
@@ -60,5 +60,10 @@
["Null txin"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]],
-"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true]
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true],
+
+["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 5528ae7243..faf911a97f 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -50,7 +50,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true],
-["Tests for CTransaction::CheckTransaction()"],
+["Tests for CheckTransaction()"],
["MAX_MONEY output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true],
@@ -67,5 +67,21 @@
["Coinbase of size 100"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
-"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true]
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true],
+
+["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true],
+
+["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true],
+
+["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"],
+[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
+ ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
+ ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]],
+ "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", true]
]
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 78953d296f..c89d218f80 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -6,8 +6,7 @@
BOOST_AUTO_TEST_SUITE(getarg_tests)
-static void
-ResetArgs(const std::string& strArg)
+static void ResetArgs(const std::string& strArg)
{
std::vector<std::string> vecArg;
boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on);
@@ -26,62 +25,50 @@ ResetArgs(const std::string& strArg)
BOOST_AUTO_TEST_CASE(boolarg)
{
ResetArgs("-foo");
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", false));
BOOST_CHECK(GetBoolArg("-foo", true));
- BOOST_CHECK(!GetBoolArg("-fo"));
BOOST_CHECK(!GetBoolArg("-fo", false));
BOOST_CHECK(GetBoolArg("-fo", true));
- BOOST_CHECK(!GetBoolArg("-fooo"));
BOOST_CHECK(!GetBoolArg("-fooo", false));
BOOST_CHECK(GetBoolArg("-fooo", true));
ResetArgs("-foo=0");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", false));
BOOST_CHECK(!GetBoolArg("-foo", true));
ResetArgs("-foo=1");
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", false));
BOOST_CHECK(GetBoolArg("-foo", true));
// New 0.6 feature: auto-map -nosomething to !-something:
ResetArgs("-nofoo");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", false));
BOOST_CHECK(!GetBoolArg("-foo", true));
ResetArgs("-nofoo=1");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", false));
BOOST_CHECK(!GetBoolArg("-foo", true));
ResetArgs("-foo -nofoo"); // -foo should win
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", false));
BOOST_CHECK(GetBoolArg("-foo", true));
ResetArgs("-foo=1 -nofoo=1"); // -foo should win
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", false));
BOOST_CHECK(GetBoolArg("-foo", true));
ResetArgs("-foo=0 -nofoo=0"); // -foo should win
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", false));
BOOST_CHECK(!GetBoolArg("-foo", true));
// New 0.6 feature: treat -- same as -:
ResetArgs("--foo=1");
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", false));
BOOST_CHECK(GetBoolArg("-foo", true));
ResetArgs("--nofoo=1");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", false));
BOOST_CHECK(!GetBoolArg("-foo", true));
@@ -133,7 +120,7 @@ BOOST_AUTO_TEST_CASE(intarg)
BOOST_AUTO_TEST_CASE(doubledash)
{
ResetArgs("--foo");
- BOOST_CHECK_EQUAL(GetBoolArg("-foo"), true);
+ BOOST_CHECK_EQUAL(GetBoolArg("-foo", false), true);
ResetArgs("--foo=verbose --bar=1");
BOOST_CHECK_EQUAL(GetArg("-foo", ""), "verbose");
@@ -143,25 +130,24 @@ BOOST_AUTO_TEST_CASE(doubledash)
BOOST_AUTO_TEST_CASE(boolargno)
{
ResetArgs("-nofoo");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", true));
BOOST_CHECK(!GetBoolArg("-foo", false));
ResetArgs("-nofoo=1");
- BOOST_CHECK(!GetBoolArg("-foo"));
BOOST_CHECK(!GetBoolArg("-foo", true));
BOOST_CHECK(!GetBoolArg("-foo", false));
ResetArgs("-nofoo=0");
- BOOST_CHECK(GetBoolArg("-foo"));
BOOST_CHECK(GetBoolArg("-foo", true));
BOOST_CHECK(GetBoolArg("-foo", false));
ResetArgs("-foo --nofoo");
- BOOST_CHECK(GetBoolArg("-foo"));
+ BOOST_CHECK(GetBoolArg("-foo", true));
+ BOOST_CHECK(GetBoolArg("-foo", false));
ResetArgs("-nofoo -foo"); // foo always wins:
- BOOST_CHECK(GetBoolArg("-foo"));
+ BOOST_CHECK(GetBoolArg("-foo", true));
+ BOOST_CHECK(GetBoolArg("-foo", false));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 0a6df88fef..c004521d1a 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -26,8 +26,8 @@ static const string strAddressBad("1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF");
#ifdef KEY_TESTS_DUMPINFO
void dumpKeyInfo(uint256 privkey)
{
- CSecret secret;
- secret.resize(32);
+ CKey key;
+ key.resize(32);
memcpy(&secret[0], &privkey, 32);
vector<unsigned char> sec;
sec.resize(32);
@@ -62,29 +62,24 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK( bsecret2C.SetString(strSecret2C));
BOOST_CHECK(!baddress1.SetString(strAddressBad));
- bool fCompressed;
- CSecret secret1 = bsecret1.GetSecret (fCompressed);
- BOOST_CHECK(fCompressed == false);
- CSecret secret2 = bsecret2.GetSecret (fCompressed);
- BOOST_CHECK(fCompressed == false);
- CSecret secret1C = bsecret1C.GetSecret(fCompressed);
- BOOST_CHECK(fCompressed == true);
- CSecret secret2C = bsecret2C.GetSecret(fCompressed);
- BOOST_CHECK(fCompressed == true);
-
- BOOST_CHECK(secret1 == secret1C);
- BOOST_CHECK(secret2 == secret2C);
-
- CKey key1, key2, key1C, key2C;
- key1.SetSecret(secret1, false);
- key2.SetSecret(secret2, false);
- key1C.SetSecret(secret1, true);
- key2C.SetSecret(secret2, true);
-
- BOOST_CHECK(addr1.Get() == CTxDestination(key1.GetPubKey().GetID()));
- BOOST_CHECK(addr2.Get() == CTxDestination(key2.GetPubKey().GetID()));
- BOOST_CHECK(addr1C.Get() == CTxDestination(key1C.GetPubKey().GetID()));
- BOOST_CHECK(addr2C.Get() == CTxDestination(key2C.GetPubKey().GetID()));
+ CKey key1 = bsecret1.GetKey();
+ BOOST_CHECK(key1.IsCompressed() == false);
+ CKey key2 = bsecret2.GetKey();
+ BOOST_CHECK(key2.IsCompressed() == false);
+ CKey key1C = bsecret1C.GetKey();
+ BOOST_CHECK(key1C.IsCompressed() == true);
+ CKey key2C = bsecret2C.GetKey();
+ BOOST_CHECK(key1C.IsCompressed() == true);
+
+ CPubKey pubkey1 = key1. GetPubKey();
+ CPubKey pubkey2 = key2. GetPubKey();
+ CPubKey pubkey1C = key1C.GetPubKey();
+ CPubKey pubkey2C = key2C.GetPubKey();
+
+ BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID()));
+ BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID()));
+ BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID()));
+ BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID()));
for (int n=0; n<16; n++)
{
@@ -100,25 +95,25 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(key1C.Sign(hashMsg, sign1C));
BOOST_CHECK(key2C.Sign(hashMsg, sign2C));
- BOOST_CHECK( key1.Verify(hashMsg, sign1));
- BOOST_CHECK(!key1.Verify(hashMsg, sign2));
- BOOST_CHECK( key1.Verify(hashMsg, sign1C));
- BOOST_CHECK(!key1.Verify(hashMsg, sign2C));
+ BOOST_CHECK( pubkey1.Verify(hashMsg, sign1));
+ BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2));
+ BOOST_CHECK( pubkey1.Verify(hashMsg, sign1C));
+ BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2C));
- BOOST_CHECK(!key2.Verify(hashMsg, sign1));
- BOOST_CHECK( key2.Verify(hashMsg, sign2));
- BOOST_CHECK(!key2.Verify(hashMsg, sign1C));
- BOOST_CHECK( key2.Verify(hashMsg, sign2C));
+ BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1));
+ BOOST_CHECK( pubkey2.Verify(hashMsg, sign2));
+ BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1C));
+ BOOST_CHECK( pubkey2.Verify(hashMsg, sign2C));
- BOOST_CHECK( key1C.Verify(hashMsg, sign1));
- BOOST_CHECK(!key1C.Verify(hashMsg, sign2));
- BOOST_CHECK( key1C.Verify(hashMsg, sign1C));
- BOOST_CHECK(!key1C.Verify(hashMsg, sign2C));
+ BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1));
+ BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2));
+ BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1C));
+ BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2C));
- BOOST_CHECK(!key2C.Verify(hashMsg, sign1));
- BOOST_CHECK( key2C.Verify(hashMsg, sign2));
- BOOST_CHECK(!key2C.Verify(hashMsg, sign1C));
- BOOST_CHECK( key2C.Verify(hashMsg, sign2C));
+ BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1));
+ BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2));
+ BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1C));
+ BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2C));
// compact signatures (with key recovery)
@@ -129,18 +124,17 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(key1C.SignCompact(hashMsg, csign1C));
BOOST_CHECK(key2C.SignCompact(hashMsg, csign2C));
- CKey rkey1, rkey2, rkey1C, rkey2C;
+ CPubKey rkey1, rkey2, rkey1C, rkey2C;
- BOOST_CHECK(rkey1.SetCompactSignature (hashMsg, csign1));
- BOOST_CHECK(rkey2.SetCompactSignature (hashMsg, csign2));
- BOOST_CHECK(rkey1C.SetCompactSignature(hashMsg, csign1C));
- BOOST_CHECK(rkey2C.SetCompactSignature(hashMsg, csign2C));
+ BOOST_CHECK(rkey1.RecoverCompact (hashMsg, csign1));
+ BOOST_CHECK(rkey2.RecoverCompact (hashMsg, csign2));
+ BOOST_CHECK(rkey1C.RecoverCompact(hashMsg, csign1C));
+ BOOST_CHECK(rkey2C.RecoverCompact(hashMsg, csign2C));
-
- BOOST_CHECK(rkey1.GetPubKey() == key1.GetPubKey());
- BOOST_CHECK(rkey2.GetPubKey() == key2.GetPubKey());
- BOOST_CHECK(rkey1C.GetPubKey() == key1C.GetPubKey());
- BOOST_CHECK(rkey2C.GetPubKey() == key2C.GetPubKey());
+ BOOST_CHECK(rkey1 == pubkey1);
+ BOOST_CHECK(rkey2 == pubkey2);
+ BOOST_CHECK(rkey1C == pubkey1C);
+ BOOST_CHECK(rkey2C == pubkey2C);
}
}
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index d6f836d367..9ef932b5b4 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -30,7 +30,7 @@ sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction,
CScript result;
result << OP_0; // CHECKMULTISIG bug workaround
- BOOST_FOREACH(CKey key, keys)
+ BOOST_FOREACH(const CKey &key, keys)
{
vector<unsigned char> vchSig;
BOOST_CHECK(key.Sign(hash, vchSig));
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index f8fe443b87..35eabed0e2 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -79,23 +79,44 @@ static Value CallRPC(string args)
}
}
-BOOST_AUTO_TEST_CASE(rpc_rawparams)
+BOOST_AUTO_TEST_CASE(rpc_wallet)
{
- // Test raw transaction API argument handling
+ // Test RPC calls for various wallet statistics
Value r;
- BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error);
-
BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
- BOOST_CHECK_THROW(r=CallRPC("listunspent 0 1 [] extra"), runtime_error);
BOOST_CHECK(r.get_array().empty());
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
+}
+
+
+BOOST_AUTO_TEST_CASE(rpc_rawparams)
+{
+ // Test raw transaction API argument handling
+ Value r;
+
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error);
+
BOOST_CHECK_THROW(CallRPC("createrawtransaction"), runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), runtime_error);
BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), runtime_error);
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index ee0d25a2f5..23cb3a8e0a 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(sign)
txFrom.vout[i+4].scriptPubKey = standardScripts[i];
txFrom.vout[i+4].nValue = COIN;
}
- BOOST_CHECK(txFrom.IsStandard());
+ BOOST_CHECK(IsStandardTx(txFrom));
CTransaction txTo[8]; // Spending transactions
for (int i = 0; i < 8; i++)
@@ -145,19 +145,19 @@ BOOST_AUTO_TEST_CASE(set)
// Test the CScript::Set* methods
CBasicKeyStore keystore;
CKey key[4];
- std::vector<CKey> keys;
+ std::vector<CPubKey> keys;
for (int i = 0; i < 4; i++)
{
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
- keys.push_back(key[i]);
+ keys.push_back(key[i].GetPubKey());
}
CScript inner[4];
inner[0].SetDestination(key[0].GetPubKey().GetID());
- inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
- inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
- inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
+ inner[1].SetMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
+ inner[2].SetMultisig(1, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
+ inner[3].SetMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+3));
CScript outer[4];
for (int i = 0; i < 4; i++)
@@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set)
txFrom.vout[i].scriptPubKey = outer[i];
txFrom.vout[i].nValue = CENT;
}
- BOOST_CHECK(txFrom.IsStandard());
+ BOOST_CHECK(IsStandardTx(txFrom));
CTransaction txTo[4]; // Spending transactions
for (int i = 0; i < 4; i++)
@@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(set)
for (int i = 0; i < 4; i++)
{
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
- BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
+ BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i]), strprintf("txTo[%d].IsStandard", i));
}
}
@@ -248,12 +248,12 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
CCoinsViewCache coins(coinsDummy);
CBasicKeyStore keystore;
CKey key[3];
- vector<CKey> keys;
+ vector<CPubKey> keys;
for (int i = 0; i < 3; i++)
{
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
- keys.push_back(key[i]);
+ keys.push_back(key[i].GetPubKey());
}
CTransaction txFrom;
@@ -305,15 +305,15 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[2].prevout.hash = txFrom.GetHash();
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
- BOOST_CHECK(txTo.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(coins), 1U);
+ BOOST_CHECK(::AreInputsStandard(txTo, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 1U);
// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
{
CScript t = txTo.vin[i].scriptSig;
txTo.vin[i].scriptSig = (CScript() << 11) + t;
- BOOST_CHECK(!txTo.AreInputsStandard(coins));
+ BOOST_CHECK(!::AreInputsStandard(txTo, coins));
txTo.vin[i].scriptSig = t;
}
@@ -329,11 +329,11 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd.vin[1].prevout.hash = txFrom.GetHash();
txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven);
- BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(coins), 11U);
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd, coins), 11U);
txToNonStd.vin[0].scriptSig.clear();
- BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 5d5a1525f7..e7ad52627c 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -211,7 +211,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
// and vice-versa)
//
result << OP_0;
- BOOST_FOREACH(CKey key, keys)
+ BOOST_FOREACH(const CKey &key, keys)
{
vector<unsigned char> vchSig;
BOOST_CHECK(key.Sign(hash, vchSig));
@@ -221,7 +221,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
return result;
}
CScript
-sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction)
+sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction)
{
std::vector<CKey> keys;
keys.push_back(key);
@@ -333,11 +333,13 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
// Test the CombineSignatures function
CBasicKeyStore keystore;
vector<CKey> keys;
+ vector<CPubKey> pubkeys;
for (int i = 0; i < 3; i++)
{
CKey key;
key.MakeNewKey(i%2 == 1);
keys.push_back(key);
+ pubkeys.push_back(key.GetPubKey());
keystore.AddKey(key);
}
@@ -390,7 +392,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_CHECK(combined == scriptSig);
// Hardest case: Multisig 2-of-3
- scriptPubKey.SetMultisig(2, keys);
+ scriptPubKey.SetMultisig(2, pubkeys);
keystore.AddCScript(scriptPubKey);
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 1762680adf..5a87f17600 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -37,12 +37,12 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
scriptSig << OP_0 << Serialize(s1);
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);
- std::vector<CKey> keys;
+ std::vector<CPubKey> keys;
for (int i = 0; i < 3; i++)
{
CKey k;
k.MakeNewKey(true);
- keys.push_back(k);
+ keys.push_back(k.GetPubKey());
}
CScript s2;
s2.SetMultisig(1, keys);
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index ddff2acd4e..53d1307b69 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
stream >> tx;
CValidationState state;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(state), strTest);
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
BOOST_CHECK(state.IsValid());
for (unsigned int i = 0; i < tx.vin.size(); i++)
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
stream >> tx;
CValidationState state;
- fValid = tx.CheckTransaction(state) && state.IsValid();
+ fValid = CheckTransaction(tx, state) && state.IsValid();
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
{
@@ -163,11 +163,11 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CTransaction tx;
stream >> tx;
CValidationState state;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(state) && state.IsValid(), "Simple deserialized transaction should be valid.");
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail
tx.vin.push_back(tx.vin[0]);
- BOOST_CHECK_MESSAGE(!tx.CheckTransaction(state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
+ BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
//
@@ -230,16 +230,16 @@ BOOST_AUTO_TEST_CASE(test_Get)
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
- BOOST_CHECK(t1.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(t1.GetValueIn(coins), (50+21+22)*CENT);
+ BOOST_CHECK(AreInputsStandard(t1, coins));
+ BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
// Adding extra junk to the scriptSig should make it non-standard:
t1.vin[0].scriptSig << OP_11;
- BOOST_CHECK(!t1.AreInputsStandard(coins));
+ BOOST_CHECK(!AreInputsStandard(t1, coins));
// ... as should not having enough:
t1.vin[0].scriptSig = CScript();
- BOOST_CHECK(!t1.AreInputsStandard(coins));
+ BOOST_CHECK(!AreInputsStandard(t1, coins));
}
BOOST_AUTO_TEST_CASE(test_IsStandard)
@@ -260,16 +260,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
key.MakeNewKey(true);
t.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
- BOOST_CHECK(t.IsStandard());
+ BOOST_CHECK(IsStandardTx(t));
t.vout[0].nValue = 5011; // dust
- BOOST_CHECK(!t.IsStandard());
+ BOOST_CHECK(!IsStandardTx(t));
t.vout[0].nValue = 6011; // not dust
- BOOST_CHECK(t.IsStandard());
+ BOOST_CHECK(IsStandardTx(t));
t.vout[0].scriptPubKey = CScript() << OP_1;
- BOOST_CHECK(!t.IsStandard());
+ BOOST_CHECK(!IsStandardTx(t));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 1b0ccad511..64bd3a1b28 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
}
BOOST_AUTO_TEST_CASE(util_MedianFilter)
-{
+{
CMedianFilter<int> filter(5, 15);
BOOST_CHECK_EQUAL(filter.median(), 15);
@@ -56,10 +56,10 @@ BOOST_AUTO_TEST_CASE(util_MedianFilter)
}
static const unsigned char ParseHex_expected[65] = {
- 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
- 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
- 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
- 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
+ 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
+ 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
+ 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
+ 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
0x5f
};
BOOST_AUTO_TEST_CASE(util_ParseHex)
@@ -123,13 +123,13 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters)
BOOST_CHECK(mapArgs.empty() && mapMultiArgs.empty());
ParseParameters(5, (char**)argv_test);
- // expectation: -ignored is ignored (program name argument),
+ // expectation: -ignored is ignored (program name argument),
// -a, -b and -ccc end up in map, -d ignored because it is after
// a non-option argument (non-GNU option parsing)
BOOST_CHECK(mapArgs.size() == 3 && mapMultiArgs.size() == 3);
- BOOST_CHECK(mapArgs.count("-a") && mapArgs.count("-b") && mapArgs.count("-ccc")
+ BOOST_CHECK(mapArgs.count("-a") && mapArgs.count("-b") && mapArgs.count("-ccc")
&& !mapArgs.count("f") && !mapArgs.count("-d"));
- BOOST_CHECK(mapMultiArgs.count("-a") && mapMultiArgs.count("-b") && mapMultiArgs.count("-ccc")
+ BOOST_CHECK(mapMultiArgs.count("-a") && mapMultiArgs.count("-b") && mapMultiArgs.count("-ccc")
&& !mapMultiArgs.count("f") && !mapMultiArgs.count("-d"));
BOOST_CHECK(mapArgs["-a"] == "" && mapArgs["-ccc"] == "multiple");
@@ -154,10 +154,10 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
BOOST_CHECK_EQUAL(GetArg("inttest1", -1), 12345);
BOOST_CHECK_EQUAL(GetArg("inttest2", -1), 81985529216486895LL);
BOOST_CHECK_EQUAL(GetArg("inttest3", -1), -1);
- BOOST_CHECK_EQUAL(GetBoolArg("booltest1"), true);
- BOOST_CHECK_EQUAL(GetBoolArg("booltest2"), false);
- BOOST_CHECK_EQUAL(GetBoolArg("booltest3"), false);
- BOOST_CHECK_EQUAL(GetBoolArg("booltest4"), true);
+ BOOST_CHECK_EQUAL(GetBoolArg("booltest1", false), true);
+ BOOST_CHECK_EQUAL(GetBoolArg("booltest2", false), false);
+ BOOST_CHECK_EQUAL(GetBoolArg("booltest3", false), false);
+ BOOST_CHECK_EQUAL(GetBoolArg("booltest4", false), true);
}
BOOST_AUTO_TEST_CASE(util_WildcardMatch)
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 3d34710d22..34836eaa97 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -6,6 +6,7 @@
#include "txdb.h"
#include "main.h"
#include "hash.h"
+#include "chainparams.h"
using namespace std;
@@ -223,7 +224,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTx = diskindex.nTx;
// Watch for genesis block
- if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
+ if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == Params().HashGenesisBlock())
pindexGenesisBlock = pindexNew;
if (!pindexNew->CheckIndex())
diff --git a/src/util.cpp b/src/util.cpp
index 4c9b897f57..bfb6d75838 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -13,6 +13,7 @@
#include <sys/resource.h>
#endif
+#include "chainparams.h"
#include "util.h"
#include "sync.h"
#include "version.h"
@@ -78,7 +79,6 @@ bool fDaemon = false;
bool fServer = false;
bool fCommandLine = false;
string strMiscWarning;
-bool fTestNet = false;
bool fNoListen = false;
bool fLogTimestamps = false;
CMedianFilter<int64> vTimeOffsets(200,0);
@@ -518,7 +518,7 @@ static void InterpretNegativeSetting(string name, map<string, string>& mapSettin
positive.append(name.begin()+3, name.end());
if (mapSettingsRet.count(positive) == 0)
{
- bool value = !GetBoolArg(name);
+ bool value = !GetBoolArg(name, false);
mapSettingsRet[positive] = (value ? "1" : "0");
}
}
@@ -1068,10 +1068,10 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
} else {
path = GetDefaultDataDir();
}
- if (fNetSpecific && GetBoolArg("-testnet", false))
- path /= "testnet3";
+ if (fNetSpecific)
+ path /= Params().DataDir();
- fs::create_directory(path);
+ fs::create_directories(path);
fCachedPath[fNetSpecific] = true;
return path;
@@ -1171,7 +1171,6 @@ bool TruncateFile(FILE *file, unsigned int length) {
#endif
}
-
// this function tries to raise the file descriptor limit to the requested number.
// It returns the actual file descriptor limit (which may be more or less than nMinFD)
int RaiseFileDescriptorLimit(int nMinFD) {
@@ -1257,8 +1256,8 @@ void ShrinkDebugFile()
fclose(file);
}
}
- else if(file != NULL)
- fclose(file);
+ else if (file != NULL)
+ fclose(file);
}
@@ -1469,15 +1468,3 @@ void RenameThread(const char* name)
(void)name;
#endif
}
-
-bool NewThread(void(*pfn)(void*), void* parg)
-{
- try
- {
- boost::thread(pfn, parg); // thread detaches when out of scope
- } catch(boost::thread_resource_error &e) {
- printf("Error creating thread: %s\n", e.what());
- return false;
- }
- return true;
-}
diff --git a/src/util.h b/src/util.h
index 3d25364505..bee2749c16 100644
--- a/src/util.h
+++ b/src/util.h
@@ -7,12 +7,12 @@
#include "uint256.h"
+#include <stdarg.h>
+
#ifndef WIN32
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
-#else
-typedef int pid_t; /* define for Windows compatibility */
#endif
#include <map>
#include <list>
@@ -20,6 +20,7 @@ typedef int pid_t; /* define for Windows compatibility */
#include <vector>
#include <string>
+#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
@@ -104,7 +105,11 @@ T* alignup(T* p)
inline void MilliSleep(int64 n)
{
-#if BOOST_VERSION >= 105000
+// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
+// until fixed in 1.52. Use the deprecated sleep method for the broken case.
+// See: https://svn.boost.org/trac/boost/ticket/7238
+
+#if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#else
boost::this_thread::sleep(boost::posix_time::milliseconds(n));
@@ -138,7 +143,6 @@ extern bool fDaemon;
extern bool fServer;
extern bool fCommandLine;
extern std::string strMiscWarning;
-extern bool fTestNet;
extern bool fNoListen;
extern bool fLogTimestamps;
extern volatile bool fReopenDebugLog;
@@ -298,7 +302,8 @@ std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
return rv;
}
-inline std::string HexStr(const std::vector<unsigned char>& vch, bool fSpaces=false)
+template<typename T>
+inline std::string HexStr(const T& vch, bool fSpaces=false)
{
return HexStr(vch.begin(), vch.end(), fSpaces);
}
@@ -389,7 +394,7 @@ int64 GetArg(const std::string& strArg, int64 nDefault);
* @param default (true or false)
* @return command-line argument or default value
*/
-bool GetBoolArg(const std::string& strArg, bool fDefault=false);
+bool GetBoolArg(const std::string& strArg, bool fDefault);
/**
* Set an argument if it doesn't already have a value
@@ -487,8 +492,6 @@ public:
}
};
-bool NewThread(void(*pfn)(void*), void* parg);
-
#ifdef WIN32
inline void SetThreadPriority(int nPriority)
{
@@ -499,7 +502,7 @@ inline void SetThreadPriority(int nPriority)
#define THREAD_PRIORITY_LOWEST PRIO_MAX
#define THREAD_PRIORITY_BELOW_NORMAL 2
#define THREAD_PRIORITY_NORMAL 0
-#define THREAD_PRIORITY_ABOVE_NORMAL 0
+#define THREAD_PRIORITY_ABOVE_NORMAL (-2)
inline void SetThreadPriority(int nPriority)
{
@@ -511,11 +514,6 @@ inline void SetThreadPriority(int nPriority)
setpriority(PRIO_PROCESS, 0, nPriority);
#endif
}
-
-inline void ExitThread(size_t nExitCode)
-{
- pthread_exit((void*)nExitCode);
-}
#endif
void RenameThread(const char* name);
@@ -529,7 +527,7 @@ inline uint32_t ByteReverse(uint32_t value)
// Standard wrapper for do-something-forever thread functions.
// "Forever" really means until the thread is interrupted.
// Use it like:
-// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
+// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
// or maybe:
// boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
@@ -542,8 +540,8 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
{
while (1)
{
- func();
MilliSleep(msecs);
+ func();
}
}
catch (boost::thread_interrupted)
diff --git a/src/wallet.cpp b/src/wallet.cpp
index c70ea20e88..488787f967 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -32,30 +32,42 @@ CPubKey CWallet::GenerateNewKey()
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
RandAddSeedPerfmon();
- CKey key;
- key.MakeNewKey(fCompressed);
+ CKey secret;
+ secret.MakeNewKey(fCompressed);
// Compressed public keys were introduced in version 0.6.0
if (fCompressed)
SetMinVersion(FEATURE_COMPRPUBKEY);
- if (!AddKey(key))
+ CPubKey pubkey = secret.GetPubKey();
+
+ // Create new metadata
+ int64 nCreationTime = GetTime();
+ mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
+ if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
+ nTimeFirstKey = nCreationTime;
+
+ if (!AddKeyPubKey(secret, pubkey))
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
- return key.GetPubKey();
+ return pubkey;
}
-bool CWallet::AddKey(const CKey& key)
+bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{
- if (!CCryptoKeyStore::AddKey(key))
+ if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
if (!fFileBacked)
return true;
- if (!IsCrypted())
- return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
+ if (!IsCrypted()) {
+ return CWalletDB(strWalletFile).WriteKey(pubkey,
+ secret.GetPrivKey(),
+ mapKeyMetadata[pubkey.GetID()]);
+ }
return true;
}
-bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
+bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
+ const vector<unsigned char> &vchCryptedSecret)
{
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
@@ -64,13 +76,26 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char
{
LOCK(cs_wallet);
if (pwalletdbEncryption)
- return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
+ return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
+ vchCryptedSecret,
+ mapKeyMetadata[vchPubKey.GetID()]);
else
- return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
+ return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
+ vchCryptedSecret,
+ mapKeyMetadata[vchPubKey.GetID()]);
}
return false;
}
+bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
+{
+ if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
+ nTimeFirstKey = meta.nCreateTime;
+
+ mapKeyMetadata[pubkey.GetID()] = meta;
+ return true;
+}
+
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
@@ -87,9 +112,6 @@ bool CWallet::AddCScript(const CScript& redeemScript)
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
- if (!IsLocked())
- return false;
-
CCrypter crypter;
CKeyingMaterial vMasterKey;
@@ -100,7 +122,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
return false;
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
- return false;
+ continue; // try another master key
if (CCryptoKeyStore::Unlock(vMasterKey))
return true;
}
@@ -460,25 +482,26 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
if (fInsertedNew || fUpdated)
if (!wtx.WriteToDisk())
return false;
-#ifndef QT_GUI
- // If default receiving address gets used, replace it with a new one
- if (vchDefaultKey.IsValid()) {
- CScript scriptDefaultKey;
- scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- if (txout.scriptPubKey == scriptDefaultKey)
+
+ if (!fHaveGUI) {
+ // If default receiving address gets used, replace it with a new one
+ if (vchDefaultKey.IsValid()) {
+ CScript scriptDefaultKey;
+ scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
- CPubKey newDefaultKey;
- if (GetKeyFromPool(newDefaultKey, false))
+ if (txout.scriptPubKey == scriptDefaultKey)
{
- SetDefaultKey(newDefaultKey);
- SetAddressBookName(vchDefaultKey.GetID(), "");
+ CPubKey newDefaultKey;
+ if (GetKeyFromPool(newDefaultKey, false))
+ {
+ SetDefaultKey(newDefaultKey);
+ SetAddressBookName(vchDefaultKey.GetID(), "");
+ }
}
}
}
}
-#endif
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
WalletUpdateSpent(wtx);
@@ -643,7 +666,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64> >& listReceived,
int64 nDebit = GetDebit();
if (nDebit > 0) // debit>0 means we signed/sent this transaction
{
- int64 nValueOut = GetValueOut();
+ int64 nValueOut = GetValueOut(*this);
nFee = nDebit - nValueOut;
}
@@ -773,14 +796,21 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
LOCK(cs_wallet);
while (pindex)
{
+ // no need to read and scan block, if block was created before
+ // our wallet birthday (as adjusted for block time variability)
+ if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
+ pindex = pindex->GetNextInMainChain();
+ continue;
+ }
+
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
}
}
return ret;
@@ -828,7 +858,7 @@ void CWallet::ReacceptWalletTransactions()
{
// Re-accept any txes of ours that aren't already in a block
if (!wtx.IsCoinBase())
- wtx.AcceptWalletTransaction(false);
+ wtx.AcceptWalletTransaction();
}
}
if (fMissing)
@@ -933,7 +963,7 @@ int64 CWallet::GetUnconfirmedBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+ if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
nTotal += pcoin->GetAvailableCredit();
}
}
@@ -965,7 +995,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
{
const CWalletTx* pcoin = &(*it).second;
- if (!pcoin->IsFinal())
+ if (!IsFinalTx(*pcoin))
continue;
if (fOnlyConfirmed && !pcoin->IsConfirmed())
@@ -1178,7 +1208,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
{
CTxOut txout(s.second, s.first);
- if (txout.IsDust())
+ if (txout.IsDust(CTransaction::nMinRelayTxFee))
{
strFailReason = _("Transaction amount too small");
return false;
@@ -1237,7 +1267,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (newTxOut.IsDust())
+ if (newTxOut.IsDust(CTransaction::nMinRelayTxFee))
{
nFeeRet += nChange;
reservekey.ReturnKey();
@@ -1276,8 +1306,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
- bool fAllowFree = CTransaction::AllowFree(dPriority);
- int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND);
+ bool fAllowFree = AllowFree(dPriority);
+ int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
if (nFeeRet < max(nPayFee, nMinFee))
{
nFeeRet = max(nPayFee, nMinFee);
@@ -1341,7 +1371,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
mapRequestCount[wtxNew.GetHash()] = 0;
// Broadcast
- if (!wtxNew.AcceptToMemoryPool(true, false))
+ if (!wtxNew.AcceptToMemoryPool(false))
{
// This must not fail. The transaction has already been signed and recorded.
printf("CommitTransaction() : Error: Transaction not valid");
@@ -1657,7 +1687,7 @@ std::map<CTxDestination, int64> CWallet::GetAddressBalances()
{
CWalletTx *pcoin = &walletEntry.second;
- if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
+ if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
continue;
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
@@ -1816,7 +1846,7 @@ void CReserveKey::ReturnKey()
vchPubKey = CPubKey();
}
-void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress)
+void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
{
setAddress.clear();
@@ -1878,3 +1908,53 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
}
+void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
+ mapKeyBirth.clear();
+
+ // get birth times for keys with metadata
+ for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
+ if (it->second.nCreateTime)
+ mapKeyBirth[it->first] = it->second.nCreateTime;
+
+ // map in which we'll infer heights of other keys
+ CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
+ std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
+ std::set<CKeyID> setKeys;
+ GetKeys(setKeys);
+ BOOST_FOREACH(const CKeyID &keyid, setKeys) {
+ if (mapKeyBirth.count(keyid) == 0)
+ mapKeyFirstBlock[keyid] = pindexMax;
+ }
+ setKeys.clear();
+
+ // if there are no such keys, we're done
+ if (mapKeyFirstBlock.empty())
+ return;
+
+ // find first block that affects those keys, if there are any left
+ std::vector<CKeyID> vAffected;
+ for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
+ // iterate over all wallet transactions...
+ const CWalletTx &wtx = (*it).second;
+ std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
+ if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
+ // ... which are already in a block
+ int nHeight = blit->second->nHeight;
+ BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
+ // iterate over all their outputs
+ ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
+ BOOST_FOREACH(const CKeyID &keyid, vAffected) {
+ // ... and all their affected keys
+ std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
+ if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
+ rit->second = blit->second;
+ }
+ vAffected.clear();
+ }
+ }
+ }
+
+ // Extract block timestamps for those keys
+ for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
+ mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
+}
diff --git a/src/wallet.h b/src/wallet.h
index dcba4675eb..36b3608fb0 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_WALLET_H
#define BITCOIN_WALLET_H
+#include "walletdb.h"
+
#include <string>
#include <vector>
@@ -16,12 +18,12 @@
#include "script.h"
#include "ui_interface.h"
#include "util.h"
-#include "walletdb.h"
class CAccountingEntry;
class CWalletTx;
class CReserveKey;
class COutput;
+class CWalletDB;
/** (client) version numbers for particular wallet features */
enum WalletFeature
@@ -85,7 +87,7 @@ public:
std::string strWalletFile;
std::set<int64> setKeyPool;
-
+ std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
@@ -121,6 +123,8 @@ public:
std::set<COutPoint> setLockedCoins;
+ int64 nTimeFirstKey;
+
// check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
@@ -136,9 +140,11 @@ public:
// Generate a new key
CPubKey GenerateNewKey();
// Adds a key to the store, and saves it to disk.
- bool AddKey(const CKey& key);
+ bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
// Adds a key to the store, without saving it to disk (used by LoadWallet)
- bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
+ bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
+ // Load metadata (used by LoadWallet)
+ bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
@@ -153,6 +159,8 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
+ void GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const;
+
/** Increment the next transaction order id
@return next transaction order id
*/
@@ -194,7 +202,7 @@ public:
void ReturnKey(int64 nIndex);
bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
int64 GetOldestKeyPoolTime();
- void GetAllReserveKeys(std::set<CKeyID>& setAddress);
+ void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, int64> GetAddressBalances();
@@ -639,7 +647,7 @@ public:
bool IsConfirmed() const
{
// Quick answer in most cases
- if (!IsFinal())
+ if (!IsFinalTx(*this))
return false;
if (GetDepthInMainChain() >= 1)
return true;
@@ -656,7 +664,7 @@ public:
{
const CMerkleTx* ptx = vWorkQueue[i];
- if (!ptx->IsFinal())
+ if (!IsFinalTx(*ptx))
return false;
if (ptx->GetDepthInMainChain() >= 1)
continue;
@@ -685,7 +693,7 @@ public:
int GetRequestCount() const;
void AddSupportingTransactions();
- bool AcceptWalletTransaction(bool fCheckInputs=true);
+ bool AcceptWalletTransaction();
void RelayWalletTransaction();
};
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 81a21443a1..702e219a5b 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -180,11 +180,27 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
return DB_LOAD_OK;
}
+class CWalletScanState {
+public:
+ unsigned int nKeys;
+ unsigned int nCKeys;
+ unsigned int nKeyMeta;
+ bool fIsEncrypted;
+ bool fAnyUnordered;
+ int nFileVersion;
+ vector<uint256> vWalletUpgrade;
+
+ CWalletScanState() {
+ nKeys = nCKeys = nKeyMeta = 0;
+ fIsEncrypted = false;
+ fAnyUnordered = false;
+ nFileVersion = 0;
+ }
+};
bool
ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
- int& nFileVersion, vector<uint256>& vWalletUpgrade,
- bool& fIsEncrypted, bool& fAnyUnordered, string& strType, string& strErr)
+ CWalletScanState &wss, string& strType, string& strErr)
{
try {
// Unserialize
@@ -204,7 +220,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CWalletTx& wtx = pwallet->mapWallet[hash];
ssValue >> wtx;
CValidationState state;
- if (wtx.CheckTransaction(state) && (wtx.GetHash() == hash) && state.IsValid())
+ if (CheckTransaction(wtx, state) && (wtx.GetHash() == hash) && state.IsValid())
wtx.BindWallet(pwallet);
else
{
@@ -229,11 +245,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str());
wtx.fTimeReceivedIsTxTime = 0;
}
- vWalletUpgrade.push_back(hash);
+ wss.vWalletUpgrade.push_back(hash);
}
if (wtx.nOrderPos == -1)
- fAnyUnordered = true;
+ wss.fAnyUnordered = true;
//// debug print
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
@@ -252,62 +268,45 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
if (nNumber > nAccountingEntryNumber)
nAccountingEntryNumber = nNumber;
- if (!fAnyUnordered)
+ if (!wss.fAnyUnordered)
{
CAccountingEntry acentry;
ssValue >> acentry;
if (acentry.nOrderPos == -1)
- fAnyUnordered = true;
+ wss.fAnyUnordered = true;
}
}
else if (strType == "key" || strType == "wkey")
{
- vector<unsigned char> vchPubKey;
+ CPubKey vchPubKey;
ssKey >> vchPubKey;
+ if (!vchPubKey.IsValid())
+ {
+ strErr = "Error reading wallet database: CPubKey corrupt";
+ return false;
+ }
CKey key;
+ CPrivKey pkey;
if (strType == "key")
{
- CPrivKey pkey;
+ wss.nKeys++;
ssValue >> pkey;
- key.SetPubKey(vchPubKey);
- if (!key.SetPrivKey(pkey))
- {
- strErr = "Error reading wallet database: CPrivKey corrupt";
- return false;
- }
- if (key.GetPubKey() != vchPubKey)
- {
- strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
- return false;
- }
- if (!key.IsValid())
- {
- strErr = "Error reading wallet database: invalid CPrivKey";
- return false;
- }
- }
- else
- {
+ } else {
CWalletKey wkey;
ssValue >> wkey;
- key.SetPubKey(vchPubKey);
- if (!key.SetPrivKey(wkey.vchPrivKey))
- {
- strErr = "Error reading wallet database: CPrivKey corrupt";
- return false;
- }
- if (key.GetPubKey() != vchPubKey)
- {
- strErr = "Error reading wallet database: CWalletKey pubkey inconsistency";
- return false;
- }
- if (!key.IsValid())
- {
- strErr = "Error reading wallet database: invalid CWalletKey";
- return false;
- }
+ pkey = wkey.vchPrivKey;
+ }
+ if (!key.SetPrivKey(pkey, vchPubKey.IsCompressed()))
+ {
+ strErr = "Error reading wallet database: CPrivKey corrupt";
+ return false;
+ }
+ if (key.GetPubKey() != vchPubKey)
+ {
+ strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
+ return false;
}
- if (!pwallet->LoadKey(key))
+ if (!pwallet->LoadKey(key, vchPubKey))
{
strErr = "Error reading wallet database: LoadKey failed";
return false;
@@ -334,12 +333,29 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> vchPubKey;
vector<unsigned char> vchPrivKey;
ssValue >> vchPrivKey;
+ wss.nCKeys++;
+
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
{
strErr = "Error reading wallet database: LoadCryptedKey failed";
return false;
}
- fIsEncrypted = true;
+ wss.fIsEncrypted = true;
+ }
+ else if (strType == "keymeta")
+ {
+ CPubKey vchPubKey;
+ ssKey >> vchPubKey;
+ CKeyMetadata keyMeta;
+ ssValue >> keyMeta;
+ wss.nKeyMeta++;
+
+ pwallet->LoadKeyMetadata(vchPubKey, keyMeta);
+
+ // find earliest key creation time, as wallet birthday
+ if (!pwallet->nTimeFirstKey ||
+ (keyMeta.nCreateTime < pwallet->nTimeFirstKey))
+ pwallet->nTimeFirstKey = keyMeta.nCreateTime;
}
else if (strType == "defaultkey")
{
@@ -349,13 +365,22 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
int64 nIndex;
ssKey >> nIndex;
+ CKeyPool keypool;
+ ssValue >> keypool;
pwallet->setKeyPool.insert(nIndex);
+
+ // If no metadata exists yet, create a default with the pool key's
+ // creation time. Note that this may be overwritten by actually
+ // stored metadata for that key later, which is fine.
+ CKeyID keyid = keypool.vchPubKey.GetID();
+ if (pwallet->mapKeyMetadata.count(keyid) == 0)
+ pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
}
else if (strType == "version")
{
- ssValue >> nFileVersion;
- if (nFileVersion == 10300)
- nFileVersion = 300;
+ ssValue >> wss.nFileVersion;
+ if (wss.nFileVersion == 10300)
+ wss.nFileVersion = 300;
}
else if (strType == "cscript")
{
@@ -389,10 +414,7 @@ static bool IsKeyType(string strType)
DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
{
pwallet->vchDefaultKey = CPubKey();
- int nFileVersion = 0;
- vector<uint256> vWalletUpgrade;
- bool fIsEncrypted = false;
- bool fAnyUnordered = false;
+ CWalletScanState wss;
bool fNoncriticalErrors = false;
DBErrors result = DB_LOAD_OK;
@@ -430,8 +452,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
// Try to be tolerant of single corrupt records:
string strType, strErr;
- if (!ReadKeyValue(pwallet, ssKey, ssValue, nFileVersion,
- vWalletUpgrade, fIsEncrypted, fAnyUnordered, strType, strErr))
+ if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
{
// losing keys is considered a catastrophic error, anything else
// we assume the user can live with:
@@ -466,19 +487,26 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (result != DB_LOAD_OK)
return result;
- printf("nFileVersion = %d\n", nFileVersion);
+ printf("nFileVersion = %d\n", wss.nFileVersion);
+
+ printf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n",
+ wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys);
- BOOST_FOREACH(uint256 hash, vWalletUpgrade)
+ // nTimeFirstKey is only reliable if all keys have metadata
+ if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta)
+ pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value'
+
+ BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade)
WriteTx(hash, pwallet->mapWallet[hash]);
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
- if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000))
+ if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000))
return DB_NEED_REWRITE;
- if (nFileVersion < CLIENT_VERSION) // Update
+ if (wss.nFileVersion < CLIENT_VERSION) // Update
WriteVersion(CLIENT_VERSION);
- if (fAnyUnordered)
+ if (wss.fAnyUnordered)
result = ReorderTransactions(pwallet);
return result;
@@ -634,10 +662,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
return false;
}
CWallet dummyWallet;
- int nFileVersion = 0;
- vector<uint256> vWalletUpgrade;
- bool fIsEncrypted = false;
- bool fAnyUnordered = false;
+ CWalletScanState wss;
DbTxn* ptxn = dbenv.TxnBegin();
BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData)
@@ -648,9 +673,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
string strType, strErr;
bool fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue,
- nFileVersion, vWalletUpgrade,
- fIsEncrypted, fAnyUnordered,
- strType, strErr);
+ wss, strType, strErr);
if (!IsKeyType(strType))
continue;
if (!fReadOK)
diff --git a/src/walletdb.h b/src/walletdb.h
index a3e779ab9d..4dfa35d82a 100644
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -11,6 +11,8 @@
class CKeyPool;
class CAccount;
class CAccountingEntry;
+class CWallet;
+class CWalletTx;
/** Error statuses for the wallet database */
enum DBErrors
@@ -23,6 +25,37 @@ enum DBErrors
DB_NEED_REWRITE
};
+class CKeyMetadata
+{
+public:
+ static const int CURRENT_VERSION=1;
+ int nVersion;
+ int64 nCreateTime; // 0 means unknown
+
+ CKeyMetadata()
+ {
+ SetNull();
+ }
+ CKeyMetadata(int64 nCreateTime_)
+ {
+ nVersion = CKeyMetadata::CURRENT_VERSION;
+ nCreateTime = nCreateTime_;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(nCreateTime);
+ )
+
+ void SetNull()
+ {
+ nVersion = CKeyMetadata::CURRENT_VERSION;
+ nCreateTime = 0;
+ }
+};
+
/** Access to the wallet database (wallet.dat) */
class CWalletDB : public CDB
{
@@ -50,21 +83,35 @@ public:
return Erase(std::make_pair(std::string("tx"), hash));
}
- bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey)
+ bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey,
+ const CKeyMetadata &keyMeta)
{
nWalletDBUpdated++;
- return Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false);
+
+ if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
+ keyMeta))
+ return false;
+
+ return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
}
- bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
+ bool WriteCryptedKey(const CPubKey& vchPubKey,
+ const std::vector<unsigned char>& vchCryptedSecret,
+ const CKeyMetadata &keyMeta)
{
+ const bool fEraseUnencryptedKey = true;
nWalletDBUpdated++;
- if (!Write(std::make_pair(std::string("ckey"), vchPubKey.Raw()), vchCryptedSecret, false))
+
+ if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
+ keyMeta))
+ return false;
+
+ if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
return false;
if (fEraseUnencryptedKey)
{
- Erase(std::make_pair(std::string("key"), vchPubKey.Raw()));
- Erase(std::make_pair(std::string("wkey"), vchPubKey.Raw()));
+ Erase(std::make_pair(std::string("key"), vchPubKey));
+ Erase(std::make_pair(std::string("wkey"), vchPubKey));
}
return true;
}
@@ -101,7 +148,7 @@ public:
bool WriteDefaultKey(const CPubKey& vchPubKey)
{
nWalletDBUpdated++;
- return Write(std::string("defaultkey"), vchPubKey.Raw());
+ return Write(std::string("defaultkey"), vchPubKey);
}
bool ReadPool(int64 nPool, CKeyPool& keypool)
@@ -160,4 +207,6 @@ public:
static bool Recover(CDBEnv& dbenv, std::string filename);
};
+bool BackupWallet(const CWallet& wallet, const std::string& strDest);
+
#endif // BITCOIN_WALLETDB_H