aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.clang-format51
-rw-r--r--src/Makefile.am35
-rw-r--r--src/Makefile.qt.include5
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include2
-rw-r--r--src/addrman.h265
-rw-r--r--src/allocators.h2
-rw-r--r--src/bitcoin-cli.cpp33
-rw-r--r--src/bitcoin-tx.cpp597
-rw-r--r--src/chainparams.cpp119
-rw-r--r--src/chainparamsbase.cpp4
-rw-r--r--src/chainparamsbase.h6
-rw-r--r--src/chainparamsseeds.h638
-rw-r--r--src/checkpoints.cpp5
-rw-r--r--src/coins.cpp15
-rw-r--r--src/coins.h18
-rw-r--r--src/compat.h19
-rw-r--r--src/compat/glibcxx_compat.cpp2
-rw-r--r--src/core.cpp16
-rw-r--r--src/core.h3
-rw-r--r--src/core_io.h28
-rw-r--r--src/core_read.cpp129
-rw-r--r--src/core_write.cpp91
-rw-r--r--src/init.cpp87
-rw-r--r--src/key.cpp10
-rw-r--r--src/keystore.h9
-rw-r--r--src/m4/bitcoin_find_bdb48.m44
-rw-r--r--src/m4/bitcoin_qt.m4109
-rw-r--r--src/main.cpp224
-rw-r--r--src/main.h9
-rw-r--r--src/miner.cpp15
-rw-r--r--src/net.cpp118
-rw-r--r--src/net.h24
-rw-r--r--src/netbase.cpp120
-rw-r--r--src/netbase.h4
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/bitcoin.cpp50
-rw-r--r--src/qt/bitcoin.qrc2
-rw-r--r--src/qt/bitcoinamountfield.cpp257
-rw-r--r--src/qt/bitcoinamountfield.h14
-rw-r--r--src/qt/bitcoingui.cpp35
-rw-r--r--src/qt/bitcoinstrings.cpp42
-rw-r--r--src/qt/bitcoinunits.cpp86
-rw-r--r--src/qt/bitcoinunits.h60
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/forms/optionsdialog.ui10
-rw-r--r--src/qt/forms/overviewpage.ui685
-rw-r--r--src/qt/forms/rpcconsole.ui364
-rw-r--r--src/qt/guiconstants.h4
-rw-r--r--src/qt/guiutil.cpp38
-rw-r--r--src/qt/guiutil.h7
-rw-r--r--src/qt/intro.cpp4
-rw-r--r--src/qt/locale/bitcoin_en.ts1307
-rw-r--r--src/qt/macdockiconhandler.mm16
-rw-r--r--src/qt/optionsdialog.cpp5
-rw-r--r--src/qt/optionsmodel.cpp10
-rw-r--r--src/qt/optionsmodel.h4
-rw-r--r--src/qt/overviewpage.cpp33
-rw-r--r--src/qt/paymentserver.cpp8
-rw-r--r--src/qt/peertablemodel.cpp63
-rw-r--r--src/qt/peertablemodel.h9
-rw-r--r--src/qt/recentrequeststablemodel.cpp7
-rw-r--r--src/qt/res/icons/toolbar.pngbin815 -> 0 bytes
-rw-r--r--src/qt/res/icons/toolbar_testnet.pngbin678 -> 0 bytes
-rw-r--r--src/qt/rpcconsole.cpp138
-rw-r--r--src/qt/rpcconsole.h27
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/sendcoinsentry.cpp18
-rw-r--r--src/qt/transactiondesc.cpp28
-rw-r--r--src/qt/transactionfilterproxy.cpp4
-rw-r--r--src/qt/transactionrecord.cpp10
-rw-r--r--src/qt/transactionrecord.h24
-rw-r--r--src/qt/transactiontablemodel.cpp30
-rw-r--r--src/qt/transactiontablemodel.h4
-rw-r--r--src/qt/transactionview.cpp21
-rw-r--r--src/qt/transactionview.h3
-rw-r--r--src/qt/walletmodel.cpp21
-rw-r--r--src/qt/walletmodel.h4
-rw-r--r--src/qt/walletview.cpp2
-rw-r--r--src/random.cpp139
-rw-r--r--src/random.h49
-rw-r--r--src/rpcblockchain.cpp70
-rw-r--r--src/rpcclient.cpp2
-rw-r--r--src/rpcdump.cpp26
-rw-r--r--src/rpcmining.cpp88
-rw-r--r--src/rpcmisc.cpp13
-rw-r--r--src/rpcnet.cpp6
-rw-r--r--src/rpcprotocol.cpp27
-rw-r--r--src/rpcprotocol.h4
-rw-r--r--src/rpcrawtransaction.cpp122
-rw-r--r--src/rpcserver.cpp207
-rw-r--r--src/rpcserver.h4
-rw-r--r--src/rpcwallet.cpp86
-rw-r--r--src/script.cpp20
-rw-r--r--src/script.h3
-rw-r--r--src/serialize.h29
-rw-r--r--src/sync.h3
-rw-r--r--src/test/canonical_tests.cpp8
-rw-r--r--src/test/crypto_tests.cpp1
-rw-r--r--src/test/data/script_invalid.json6
-rw-r--r--src/test/data/script_valid.json4
-rw-r--r--src/test/mruset_tests.cpp1
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/script_P2SH_tests.cpp3
-rw-r--r--src/test/script_tests.cpp74
-rw-r--r--src/test/sighash_tests.cpp19
-rw-r--r--src/test/skiplist_tests.cpp7
-rw-r--r--src/test/test_bitcoin.cpp4
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/util_tests.cpp1
-rw-r--r--src/timedata.cpp20
-rw-r--r--src/txmempool.cpp37
-rw-r--r--src/ui_interface.h5
-rw-r--r--src/uint256.cpp43
-rw-r--r--src/uint256.h4
-rw-r--r--src/univalue/univalue.cpp211
-rw-r--r--src/univalue/univalue.h155
-rw-r--r--src/univalue/univalue_read.cpp390
-rw-r--r--src/univalue/univalue_write.cpp145
-rw-r--r--src/util.cpp121
-rw-r--r--src/util.h50
-rw-r--r--src/version.h4
-rw-r--r--src/wallet.cpp90
-rw-r--r--src/wallet.h25
124 files changed, 5912 insertions, 2702 deletions
diff --git a/src/.clang-format b/src/.clang-format
new file mode 100644
index 0000000000..226a15d185
--- /dev/null
+++ b/src/.clang-format
@@ -0,0 +1,51 @@
+AccessModifierOffset: -4
+AlignEscapedNewlinesLeft: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackParameters: false
+BreakBeforeBinaryOperators: false
+BreakBeforeBraces: Linux
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit: 0
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, BOOST_REVERSE_FOREACH ]
+IndentCaseLabels: false
+IndentFunctionDeclarationAfterType: false
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: false
+Language: Cpp
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Never
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b0b97b7ac..727a88c3e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,7 @@ LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CLI=libbitcoin_cli.a
LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
+LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
LIBBITCOINQT=qt/libbitcoinqt.a
noinst_LIBRARIES = \
@@ -41,6 +42,7 @@ noinst_LIBRARIES = \
libbitcoin_common.a \
libbitcoin_cli.a \
libbitcoin_util.a \
+ univalue/libbitcoin_univalue.a \
crypto/libbitcoin_crypto.a
if ENABLE_WALLET
BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
@@ -58,6 +60,8 @@ if BUILD_BITCOIN_CLI
bin_PROGRAMS += bitcoin-cli
endif
+bin_PROGRAMS += bitcoin-tx
+
.PHONY: FORCE
# bitcoin core #
BITCOIN_CORE_H = \
@@ -68,6 +72,7 @@ BITCOIN_CORE_H = \
bloom.h \
chainparams.h \
chainparamsbase.h \
+ chainparamsseeds.h \
checkpoints.h \
checkqueue.h \
clientversion.h \
@@ -75,6 +80,7 @@ BITCOIN_CORE_H = \
coins.h \
compat.h \
core.h \
+ core_io.h \
crypter.h \
db.h \
hash.h \
@@ -91,6 +97,7 @@ BITCOIN_CORE_H = \
noui.h \
pow.h \
protocol.h \
+ random.h \
rpcclient.h \
rpcprotocol.h \
rpcserver.h \
@@ -176,6 +183,13 @@ crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha1.h \
crypto/ripemd160.h
+# univalue JSON library
+univalue_libbitcoin_univalue_a_SOURCES = \
+ univalue/univalue.cpp \
+ univalue/univalue_read.cpp \
+ univalue/univalue_write.cpp \
+ univalue/univalue.h
+
# common: shared between bitcoind, and bitcoin-qt and non-server tools
libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_common_a_SOURCES = \
@@ -184,6 +198,8 @@ libbitcoin_common_a_SOURCES = \
chainparams.cpp \
coins.cpp \
core.cpp \
+ core_read.cpp \
+ core_write.cpp \
hash.cpp \
key.cpp \
keystore.cpp \
@@ -197,14 +213,15 @@ libbitcoin_common_a_SOURCES = \
# backward-compatibility objects and their sanity checks are linked.
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_util_a_SOURCES = \
+ compat/glibc_sanity.cpp \
+ compat/glibcxx_sanity.cpp \
chainparamsbase.cpp \
+ random.cpp \
rpcprotocol.cpp \
sync.cpp \
uint256.cpp \
util.cpp \
version.cpp \
- compat/glibc_sanity.cpp \
- compat/glibcxx_sanity.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
@@ -224,6 +241,7 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
bitcoind_LDADD = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_UNIVALUE) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO) \
$(LIBLEVELDB) \
@@ -262,6 +280,17 @@ endif
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
#
+# bitcoin-tx binary #
+bitcoin_tx_LDADD = \
+ $(LIBBITCOIN_UNIVALUE) \
+ $(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_CRYPTO) \
+ $(BOOST_LIBS)
+bitcoin_tx_SOURCES = bitcoin-tx.cpp
+bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
+#
+
if TARGET_WINDOWS
bitcoin_cli_SOURCES += bitcoin-cli-res.rc
endif
@@ -274,7 +303,7 @@ EXTRA_DIST = leveldb secp256k1
clean-local:
-$(MAKE) -C leveldb clean
- -$(MAKE) -C secp256k1 clean
+ -$(MAKE) -C secp256k1 clean 2>/dev/null
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
-rm -f config.h
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 75b7b683dd..7e6fa5cb88 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -145,6 +145,7 @@ BITCOIN_MM = \
QT_MOC = \
qt/bitcoin.moc \
+ qt/bitcoinamountfield.moc \
qt/intro.moc \
qt/overviewpage.moc \
qt/rpcconsole.moc
@@ -244,8 +245,6 @@ RES_ICONS = \
qt/res/icons/remove.png \
qt/res/icons/send.png \
qt/res/icons/synced.png \
- qt/res/icons/toolbar.png \
- qt/res/icons/toolbar_testnet.png \
qt/res/icons/transaction0.png \
qt/res/icons/transaction2.png \
qt/res/icons/transaction_conflicted.png \
@@ -358,7 +357,7 @@ qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER)
if ENABLE_WALLET
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \
+qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
if USE_LIBSECP256K1
qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 51ce006fc1..d49b2240ea 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -30,7 +30,7 @@ qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER)
if ENABLE_WALLET
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
-qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \
+qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) \
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
if USE_LIBSECP256K1
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 12b90adca3..72451fba9a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -64,7 +64,7 @@ endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
-test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \
+test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
diff --git a/src/addrman.h b/src/addrman.h
index c4c296560e..052d364655 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -7,6 +7,7 @@
#include "netbase.h"
#include "protocol.h"
+#include "random.h"
#include "sync.h"
#include "timedata.h"
#include "util.h"
@@ -16,8 +17,6 @@
#include <stdint.h>
#include <vector>
-#include <openssl/rand.h>
-
/** Extended statistics about a CAddress */
class CAddrInfo : public CAddress
{
@@ -246,145 +245,147 @@ protected:
void Connected_(const CService &addr, int64_t nTime);
public:
+ // serialized format:
+ // * version byte (currently 0)
+ // * nKey
+ // * nNew
+ // * nTried
+ // * number of "new" buckets
+ // * all nNew addrinfos in vvNew
+ // * all nTried addrinfos in vvTried
+ // * for each bucket:
+ // * number of elements
+ // * for each element: index
+ //
+ // Notice that vvTried, mapAddr and vVector are never encoded explicitly;
+ // they are instead reconstructed from the other information.
+ //
+ // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
+ // otherwise it is reconstructed as well.
+ //
+ // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
+ // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
+ //
+ // We don't use IMPLEMENT_SERIALIZE since the serialization and deserialization code has
+ // very little in common.
+ template<typename Stream>
+ void Serialize(Stream &s, int nType, int nVersionDummy) const
+ {
+ LOCK(cs);
+
+ unsigned char nVersion = 0;
+ s << nVersion;
+ s << nKey;
+ s << nNew;
+ s << nTried;
+
+ int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
+ s << nUBuckets;
+ std::map<int, int> mapUnkIds;
+ int nIds = 0;
+ for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
+ if (nIds == nNew) break; // this means nNew was wrong, oh ow
+ mapUnkIds[(*it).first] = nIds;
+ const CAddrInfo &info = (*it).second;
+ if (info.nRefCount) {
+ s << info;
+ nIds++;
+ }
+ }
+ nIds = 0;
+ for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
+ if (nIds == nTried) break; // this means nTried was wrong, oh ow
+ const CAddrInfo &info = (*it).second;
+ if (info.fInTried) {
+ s << info;
+ nIds++;
+ }
+ }
+ for (std::vector<std::set<int> >::const_iterator it = vvNew.begin(); it != vvNew.end(); it++) {
+ const std::set<int> &vNew = (*it);
+ int nSize = vNew.size();
+ s << nSize;
+ for (std::set<int>::const_iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) {
+ int nIndex = mapUnkIds[*it2];
+ s << nIndex;
+ }
+ }
+ }
- IMPLEMENT_SERIALIZE
- (({
- // serialized format:
- // * version byte (currently 0)
- // * nKey
- // * nNew
- // * nTried
- // * number of "new" buckets
- // * all nNew addrinfos in vvNew
- // * all nTried addrinfos in vvTried
- // * for each bucket:
- // * number of elements
- // * for each element: index
- //
- // Notice that vvTried, mapAddr and vVector are never encoded explicitly;
- // they are instead reconstructed from the other information.
- //
- // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
- // otherwise it is reconstructed as well.
- //
- // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
- // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
- {
- LOCK(cs);
- unsigned char nVersion = 0;
- READWRITE(nVersion);
- READWRITE(nKey);
- READWRITE(nNew);
- READWRITE(nTried);
-
- CAddrMan *am = const_cast<CAddrMan*>(this);
- if (fWrite)
- {
- int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
- READWRITE(nUBuckets);
- std::map<int, int> mapUnkIds;
- int nIds = 0;
- for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
- {
- if (nIds == nNew) break; // this means nNew was wrong, oh ow
- mapUnkIds[(*it).first] = nIds;
- CAddrInfo &info = (*it).second;
- if (info.nRefCount)
- {
- READWRITE(info);
- nIds++;
- }
- }
- nIds = 0;
- for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
- {
- if (nIds == nTried) break; // this means nTried was wrong, oh ow
- CAddrInfo &info = (*it).second;
- if (info.fInTried)
- {
- READWRITE(info);
- nIds++;
- }
- }
- for (std::vector<std::set<int> >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++)
- {
- const std::set<int> &vNew = (*it);
- int nSize = vNew.size();
- READWRITE(nSize);
- for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
- {
- int nIndex = mapUnkIds[*it2];
- READWRITE(nIndex);
- }
- }
+ template<typename Stream>
+ void Unserialize(Stream& s, int nType, int nVersionDummy)
+ {
+ LOCK(cs);
+
+ unsigned char nVersion;
+ s >> nVersion;
+ s >> nKey;
+ s >> nNew;
+ s >> nTried;
+
+ int nUBuckets = 0;
+ s >> nUBuckets;
+ nIdCount = 0;
+ mapInfo.clear();
+ mapAddr.clear();
+ vRandom.clear();
+ vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
+ vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
+ for (int n = 0; n < nNew; n++) {
+ CAddrInfo &info = mapInfo[n];
+ s >> info;
+ mapAddr[info] = n;
+ info.nRandomPos = vRandom.size();
+ vRandom.push_back(n);
+ if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) {
+ vvNew[info.GetNewBucket(nKey)].insert(n);
+ info.nRefCount++;
+ }
+ }
+ nIdCount = nNew;
+ int nLost = 0;
+ for (int n = 0; n < nTried; n++) {
+ CAddrInfo info;
+ s >> info;
+ std::vector<int> &vTried = vvTried[info.GetTriedBucket(nKey)];
+ if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) {
+ info.nRandomPos = vRandom.size();
+ info.fInTried = true;
+ vRandom.push_back(nIdCount);
+ mapInfo[nIdCount] = info;
+ mapAddr[info] = nIdCount;
+ vTried.push_back(nIdCount);
+ nIdCount++;
} else {
- int nUBuckets = 0;
- READWRITE(nUBuckets);
- am->nIdCount = 0;
- am->mapInfo.clear();
- am->mapAddr.clear();
- am->vRandom.clear();
- am->vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
- am->vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
- for (int n = 0; n < am->nNew; n++)
- {
- CAddrInfo &info = am->mapInfo[n];
- READWRITE(info);
- am->mapAddr[info] = n;
- info.nRandomPos = vRandom.size();
- am->vRandom.push_back(n);
- if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
- {
- am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
- info.nRefCount++;
- }
- }
- am->nIdCount = am->nNew;
- int nLost = 0;
- for (int n = 0; n < am->nTried; n++)
- {
- CAddrInfo info;
- READWRITE(info);
- std::vector<int> &vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
- if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
- {
- info.nRandomPos = vRandom.size();
- info.fInTried = true;
- am->vRandom.push_back(am->nIdCount);
- am->mapInfo[am->nIdCount] = info;
- am->mapAddr[info] = am->nIdCount;
- vTried.push_back(am->nIdCount);
- am->nIdCount++;
- } else {
- nLost++;
- }
- }
- am->nTried -= nLost;
- for (int b = 0; b < nUBuckets; b++)
- {
- std::set<int> &vNew = am->vvNew[b];
- int nSize = 0;
- READWRITE(nSize);
- for (int n = 0; n < nSize; n++)
- {
- int nIndex = 0;
- READWRITE(nIndex);
- CAddrInfo &info = am->mapInfo[nIndex];
- if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
- {
- info.nRefCount++;
- vNew.insert(nIndex);
- }
- }
+ nLost++;
+ }
+ }
+ nTried -= nLost;
+ for (int b = 0; b < nUBuckets; b++) {
+ std::set<int> &vNew = vvNew[b];
+ int nSize = 0;
+ s >> nSize;
+ for (int n = 0; n < nSize; n++) {
+ int nIndex = 0;
+ s >> nIndex;
+ CAddrInfo &info = mapInfo[nIndex];
+ if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) {
+ info.nRefCount++;
+ vNew.insert(nIndex);
}
}
}
- });)
+ }
+
+ unsigned int GetSerializeSize(int nType, int nVersion) const
+ {
+ return (CSizeComputer(nType, nVersion) << *this).size();
+ }
CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
{
nKey.resize(32);
- RAND_bytes(&nKey[0], 32);
+ GetRandBytes(&nKey[0], 32);
nIdCount = 0;
nTried = 0;
diff --git a/src/allocators.h b/src/allocators.h
index 7012ef7e2a..be0be7ab96 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -131,7 +131,7 @@ public:
* Due to the unpredictable order of static initializers, we have to make sure the
* LockedPageManager instance exists before any other STL-based objects that use
* secure_allocator are created. So instead of having LockedPageManager also be
- * static-intialized, it is created on demand.
+ * static-initialized, it is created on demand.
*/
class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
{
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 016b2f50f5..0609adcab3 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -50,8 +50,7 @@ static bool AppInitRPC(int argc, char* argv[])
// Parameters
//
ParseParameters(argc, argv);
- if (!boost::filesystem::is_directory(GetDataDir(false)))
- {
+ if (!boost::filesystem::is_directory(GetDataDir(false))) {
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
return false;
}
@@ -66,11 +65,9 @@ static bool AppInitRPC(int argc, char* argv[])
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
return false;
}
- if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
- {
+ if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
- if (!mapArgs.count("-version"))
- {
+ if (!mapArgs.count("-version")) {
strUsage += "\n" + _("Usage:") + "\n" +
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
" bitcoin-cli [options] help " + _("List commands") + "\n" +
@@ -129,7 +126,7 @@ Object CallRPC(const string& strMethod, const Array& params)
// Receive HTTP reply message headers and body
map<string, string> mapHeaders;
string strReply;
- ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
+ ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
if (nStatus == HTTP_UNAUTHORIZED)
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
@@ -153,11 +150,9 @@ int CommandLineRPC(int argc, char *argv[])
{
string strPrint;
int nRet = 0;
- try
- {
+ try {
// Skip switches
- while (argc > 1 && IsSwitchChar(argv[1][0]))
- {
+ while (argc > 1 && IsSwitchChar(argv[1][0])) {
argc--;
argv++;
}
@@ -178,15 +173,12 @@ int CommandLineRPC(int argc, char *argv[])
const Value& result = find_value(reply, "result");
const Value& error = find_value(reply, "error");
- if (error.type() != null_type)
- {
+ if (error.type() != null_type) {
// Error
strPrint = "error: " + write_string(error, false);
int code = find_value(error.get_obj(), "code").get_int();
nRet = abs(code);
- }
- else
- {
+ } else {
// Result
if (result.type() == null_type)
strPrint = "";
@@ -208,8 +200,7 @@ int CommandLineRPC(int argc, char *argv[])
throw;
}
- if (strPrint != "")
- {
+ if (strPrint != "") {
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
}
return nRet;
@@ -219,8 +210,7 @@ int main(int argc, char* argv[])
{
SetupEnvironment();
- try
- {
+ try {
if(!AppInitRPC(argc, argv))
return EXIT_FAILURE;
}
@@ -233,8 +223,7 @@ int main(int argc, char* argv[])
}
int ret = EXIT_FAILURE;
- try
- {
+ try {
ret = CommandLineRPC(argc, argv);
}
catch (std::exception& e) {
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
new file mode 100644
index 0000000000..299315424b
--- /dev/null
+++ b/src/bitcoin-tx.cpp
@@ -0,0 +1,597 @@
+// Copyright (c) 2009-2014 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 "base58.h"
+#include "util.h"
+#include "core.h"
+#include "main.h" // for MAX_BLOCK_SIZE
+#include "keystore.h"
+#include "ui_interface.h" // for _(...)
+#include "univalue/univalue.h"
+#include "core_io.h"
+
+#include <stdio.h>
+#include <boost/assign/list_of.hpp>
+
+using namespace std;
+using namespace boost::assign;
+
+static bool fCreateBlank;
+static map<string,UniValue> registers;
+CClientUIInterface uiInterface;
+
+static bool AppInitRawTx(int argc, char* argv[])
+{
+ //
+ // Parameters
+ //
+ ParseParameters(argc, argv);
+
+ // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
+ if (!SelectParamsFromCommandLine()) {
+ fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
+ return false;
+ }
+
+ fCreateBlank = GetBoolArg("-create", false);
+
+ if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help"))
+ {
+ // First part of help message is specific to this utility
+ std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" +
+ _("Usage:") + "\n" +
+ " bitcoin-tx [options] <hex-tx> [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" +
+ " bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" +
+ "\n";
+
+ fprintf(stdout, "%s", strUsage.c_str());
+
+ strUsage = _("Options:") + "\n";
+ strUsage += " -? " + _("This help message") + "\n";
+ strUsage += " -create " + _("Create new, empty TX.") + "\n";
+ strUsage += " -json " + _("Select JSON output") + "\n";
+ strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
+ strUsage += " -testnet " + _("Use the test network") + "\n";
+ strUsage += "\n";
+
+ fprintf(stdout, "%s", strUsage.c_str());
+
+
+ strUsage = _("Commands:") + "\n";
+ strUsage += " delin=N " + _("Delete input N from TX") + "\n";
+ strUsage += " delout=N " + _("Delete output N from TX") + "\n";
+ strUsage += " in=TXID:VOUT " + _("Add input to TX") + "\n";
+ strUsage += " locktime=N " + _("Set TX lock time to N") + "\n";
+ strUsage += " nversion=N " + _("Set TX version to N") + "\n";
+ strUsage += " outaddr=VALUE:ADDRESS " + _("Add address-based output to TX") + "\n";
+ strUsage += " outscript=VALUE:SCRIPT " + _("Add raw script output to TX") + "\n";
+ strUsage += " sign=SIGHASH-FLAGS " + _("Add zero or more signatures to transaction") + "\n";
+ strUsage += " This command requires JSON registers:\n";
+ strUsage += " prevtxs=JSON object\n";
+ strUsage += " privatekeys=JSON object\n";
+ strUsage += " See signrawtransaction docs for format of sighash flags, JSON objects.\n";
+ strUsage += "\n";
+ fprintf(stdout, "%s", strUsage.c_str());
+
+ strUsage = _("Register Commands:") + "\n";
+ strUsage += " load=NAME:FILENAME " + _("Load JSON file FILENAME into register NAME") + "\n";
+ strUsage += " set=NAME:JSON-STRING " + _("Set register NAME to given JSON-STRING") + "\n";
+ strUsage += "\n";
+ fprintf(stdout, "%s", strUsage.c_str());
+
+ return false;
+ }
+ return true;
+}
+
+static void RegisterSetJson(const string& key, const string& rawJson)
+{
+ UniValue val;
+ if (!val.read(rawJson)) {
+ string strErr = "Cannot parse JSON for key " + key;
+ throw runtime_error(strErr);
+ }
+
+ registers[key] = val;
+}
+
+static void RegisterSet(const string& strInput)
+{
+ // separate NAME:VALUE in string
+ size_t pos = strInput.find(':');
+ if ((pos == string::npos) ||
+ (pos == 0) ||
+ (pos == (strInput.size() - 1)))
+ throw runtime_error("Register input requires NAME:VALUE");
+
+ string key = strInput.substr(0, pos);
+ string valStr = strInput.substr(pos + 1, string::npos);
+
+ RegisterSetJson(key, valStr);
+}
+
+static void RegisterLoad(const string& strInput)
+{
+ // separate NAME:FILENAME in string
+ size_t pos = strInput.find(':');
+ if ((pos == string::npos) ||
+ (pos == 0) ||
+ (pos == (strInput.size() - 1)))
+ throw runtime_error("Register load requires NAME:FILENAME");
+
+ string key = strInput.substr(0, pos);
+ string filename = strInput.substr(pos + 1, string::npos);
+
+ FILE *f = fopen(filename.c_str(), "r");
+ if (!f) {
+ string strErr = "Cannot open file " + filename;
+ throw runtime_error(strErr);
+ }
+
+ // load file chunks into one big buffer
+ string valStr;
+ while ((!feof(f)) && (!ferror(f))) {
+ char buf[4096];
+ int bread = fread(buf, 1, sizeof(buf), f);
+ if (bread <= 0)
+ break;
+
+ valStr.insert(valStr.size(), buf, bread);
+ }
+
+ if (ferror(f)) {
+ string strErr = "Error reading file " + filename;
+ throw runtime_error(strErr);
+ }
+
+ fclose(f);
+
+ // evaluate as JSON buffer register
+ RegisterSetJson(key, valStr);
+}
+
+static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
+{
+ int64_t newVersion = atoi64(cmdVal);
+ if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
+ throw runtime_error("Invalid TX version requested");
+
+ tx.nVersion = (int) newVersion;
+}
+
+static void MutateTxLocktime(CMutableTransaction& tx, const string& cmdVal)
+{
+ int64_t newLocktime = atoi64(cmdVal);
+ if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
+ throw runtime_error("Invalid TX locktime requested");
+
+ tx.nLockTime = (unsigned int) newLocktime;
+}
+
+static void MutateTxAddInput(CMutableTransaction& tx, const string& strInput)
+{
+ // separate TXID:VOUT in string
+ size_t pos = strInput.find(':');
+ if ((pos == string::npos) ||
+ (pos == 0) ||
+ (pos == (strInput.size() - 1)))
+ throw runtime_error("TX input missing separator");
+
+ // extract and validate TXID
+ string strTxid = strInput.substr(0, pos);
+ if ((strTxid.size() != 64) || !IsHex(strTxid))
+ throw runtime_error("invalid TX input txid");
+ uint256 txid(strTxid);
+
+ static const unsigned int minTxOutSz = 9;
+ static const unsigned int maxVout = MAX_BLOCK_SIZE / minTxOutSz;
+
+ // extract and validate vout
+ string strVout = strInput.substr(pos + 1, string::npos);
+ int vout = atoi(strVout);
+ if ((vout < 0) || (vout > (int)maxVout))
+ throw runtime_error("invalid TX input vout");
+
+ // append to transaction input list
+ CTxIn txin(txid, vout);
+ tx.vin.push_back(txin);
+}
+
+static void MutateTxAddOutAddr(CMutableTransaction& tx, const string& strInput)
+{
+ // separate VALUE:ADDRESS in string
+ size_t pos = strInput.find(':');
+ if ((pos == string::npos) ||
+ (pos == 0) ||
+ (pos == (strInput.size() - 1)))
+ throw runtime_error("TX output missing separator");
+
+ // extract and validate VALUE
+ string strValue = strInput.substr(0, pos);
+ int64_t value;
+ if (!ParseMoney(strValue, value))
+ throw runtime_error("invalid TX output value");
+
+ // extract and validate ADDRESS
+ string strAddr = strInput.substr(pos + 1, string::npos);
+ CBitcoinAddress addr(strAddr);
+ if (!addr.IsValid())
+ throw runtime_error("invalid TX output address");
+
+ // build standard output script via SetDestination()
+ CScript scriptPubKey;
+ scriptPubKey.SetDestination(addr.Get());
+
+ // construct TxOut, append to transaction output list
+ CTxOut txout(value, scriptPubKey);
+ tx.vout.push_back(txout);
+}
+
+static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput)
+{
+ // separate VALUE:SCRIPT in string
+ size_t pos = strInput.find(':');
+ if ((pos == string::npos) ||
+ (pos == 0) ||
+ (pos == (strInput.size() - 1)))
+ throw runtime_error("TX output missing separator");
+
+ // extract and validate VALUE
+ string strValue = strInput.substr(0, pos);
+ int64_t value;
+ if (!ParseMoney(strValue, value))
+ throw runtime_error("invalid TX output value");
+
+ // extract and validate script
+ string strScript = strInput.substr(pos + 1, string::npos);
+ CScript scriptPubKey = ParseScript(strScript); // throws on err
+
+ // construct TxOut, append to transaction output list
+ CTxOut txout(value, scriptPubKey);
+ tx.vout.push_back(txout);
+}
+
+static void MutateTxDelInput(CMutableTransaction& tx, const string& strInIdx)
+{
+ // parse requested deletion index
+ int inIdx = atoi(strInIdx);
+ if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
+ string strErr = "Invalid TX input index '" + strInIdx + "'";
+ throw runtime_error(strErr.c_str());
+ }
+
+ // delete input from transaction
+ tx.vin.erase(tx.vin.begin() + inIdx);
+}
+
+static void MutateTxDelOutput(CMutableTransaction& tx, const string& strOutIdx)
+{
+ // parse requested deletion index
+ int outIdx = atoi(strOutIdx);
+ if (outIdx < 0 || outIdx >= (int)tx.vout.size()) {
+ string strErr = "Invalid TX output index '" + strOutIdx + "'";
+ throw runtime_error(strErr.c_str());
+ }
+
+ // delete output from transaction
+ tx.vout.erase(tx.vout.begin() + outIdx);
+}
+
+static const unsigned int N_SIGHASH_OPTS = 6;
+static const struct {
+ const char *flagStr;
+ int flags;
+} sighashOptions[N_SIGHASH_OPTS] = {
+ "ALL", SIGHASH_ALL,
+ "NONE", SIGHASH_NONE,
+ "SINGLE", SIGHASH_SINGLE,
+ "ALL|ANYONECANPAY", SIGHASH_ALL|SIGHASH_ANYONECANPAY,
+ "NONE|ANYONECANPAY", SIGHASH_NONE|SIGHASH_ANYONECANPAY,
+ "SINGLE|ANYONECANPAY", SIGHASH_SINGLE|SIGHASH_ANYONECANPAY,
+};
+
+static bool findSighashFlags(int& flags, const string& flagStr)
+{
+ flags = 0;
+
+ for (unsigned int i = 0; i < N_SIGHASH_OPTS; i++) {
+ if (flagStr == sighashOptions[i].flagStr) {
+ flags = sighashOptions[i].flags;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint256 ParseHashUO(map<string,UniValue>& o, string strKey)
+{
+ if (!o.count(strKey))
+ return 0;
+ return ParseHashUV(o[strKey], strKey);
+}
+
+vector<unsigned char> ParseHexUO(map<string,UniValue>& o, string strKey)
+{
+ if (!o.count(strKey)) {
+ vector<unsigned char> emptyVec;
+ return emptyVec;
+ }
+ return ParseHexUV(o[strKey], strKey);
+}
+
+static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
+{
+ int nHashType = SIGHASH_ALL;
+
+ if (flagStr.size() > 0)
+ if (!findSighashFlags(nHashType, flagStr))
+ throw runtime_error("unknown sighash flag/sign option");
+
+ vector<CTransaction> txVariants;
+ txVariants.push_back(tx);
+
+ // mergedTx will end up with all the signatures; it
+ // starts as a clone of the raw tx:
+ CMutableTransaction mergedTx(txVariants[0]);
+ bool fComplete = true;
+ CCoinsView viewDummy;
+ CCoinsViewCache view(viewDummy);
+
+ if (!registers.count("privatekeys"))
+ throw runtime_error("privatekeys register variable must be set.");
+ bool fGivenKeys = false;
+ CBasicKeyStore tempKeystore;
+ UniValue keysObj = registers["privatekeys"];
+ fGivenKeys = true;
+
+ for (unsigned int kidx = 0; kidx < keysObj.count(); kidx++) {
+ if (!keysObj[kidx].isStr())
+ throw runtime_error("privatekey not a string");
+ CBitcoinSecret vchSecret;
+ bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
+ if (!fGood)
+ throw runtime_error("privatekey not valid");
+
+ CKey key = vchSecret.GetKey();
+ tempKeystore.AddKey(key);
+ }
+
+ // Add previous txouts given in the RPC call:
+ if (!registers.count("prevtxs"))
+ throw runtime_error("prevtxs register variable must be set.");
+ UniValue prevtxsObj = registers["privatekeys"];
+ {
+ for (unsigned int previdx = 0; previdx < prevtxsObj.count(); previdx++) {
+ UniValue prevOut = prevtxsObj[previdx];
+ if (!prevOut.isObject())
+ throw runtime_error("expected prevtxs internal object");
+
+ map<string,UniValue::VType> types = map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR);
+ if (!prevOut.checkObject(types))
+ throw runtime_error("prevtxs internal object typecheck fail");
+
+ uint256 txid = ParseHashUV(prevOut, "txid");
+
+ int nOut = atoi(prevOut["vout"].getValStr());
+ if (nOut < 0)
+ throw runtime_error("vout must be positive");
+
+ vector<unsigned char> pkData(ParseHexUV(prevOut, "scriptPubKey"));
+ CScript scriptPubKey(pkData.begin(), pkData.end());
+
+ CCoins coins;
+ if (view.GetCoins(txid, coins)) {
+ if (coins.IsAvailable(nOut) && coins.vout[nOut].scriptPubKey != scriptPubKey) {
+ string err("Previous output scriptPubKey mismatch:\n");
+ err = err + coins.vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
+ scriptPubKey.ToString();
+ throw runtime_error(err);
+ }
+ // what todo if txid is known, but the actual output isn't?
+ }
+ if ((unsigned int)nOut >= coins.vout.size())
+ coins.vout.resize(nOut+1);
+ coins.vout[nOut].scriptPubKey = scriptPubKey;
+ coins.vout[nOut].nValue = 0; // we don't know the actual output value
+ view.SetCoins(txid, coins);
+
+ // if redeemScript given and private keys given,
+ // add redeemScript to the tempKeystore so it can be signed:
+ if (fGivenKeys && scriptPubKey.IsPayToScriptHash() &&
+ prevOut.exists("redeemScript")) {
+ UniValue v = prevOut["redeemScript"];
+ vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));
+ CScript redeemScript(rsData.begin(), rsData.end());
+ tempKeystore.AddCScript(redeemScript);
+ }
+ }
+ }
+
+ const CKeyStore& keystore = tempKeystore;
+
+ bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
+
+ // Sign what we can:
+ for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
+ CTxIn& txin = mergedTx.vin[i];
+ CCoins coins;
+ if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n)) {
+ fComplete = false;
+ continue;
+ }
+ const CScript& prevPubKey = coins.vout[txin.prevout.n].scriptPubKey;
+
+ txin.scriptSig.clear();
+ // Only sign SIGHASH_SINGLE if there's a corresponding output:
+ if (!fHashSingle || (i < mergedTx.vout.size()))
+ SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
+
+ // ... and merge in other signatures:
+ BOOST_FOREACH(const CTransaction& txv, txVariants) {
+ txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
+ }
+ if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS, 0))
+ fComplete = false;
+ }
+
+ if (fComplete) {
+ // do nothing... for now
+ // perhaps store this for later optional JSON output
+ }
+
+ tx = mergedTx;
+}
+
+static void MutateTx(CMutableTransaction& tx, const string& command,
+ const string& commandVal)
+{
+ if (command == "nversion")
+ MutateTxVersion(tx, commandVal);
+ else if (command == "locktime")
+ MutateTxLocktime(tx, commandVal);
+
+ else if (command == "delin")
+ MutateTxDelInput(tx, commandVal);
+ else if (command == "in")
+ MutateTxAddInput(tx, commandVal);
+
+ else if (command == "delout")
+ MutateTxDelOutput(tx, commandVal);
+ else if (command == "outaddr")
+ MutateTxAddOutAddr(tx, commandVal);
+ else if (command == "outscript")
+ MutateTxAddOutScript(tx, commandVal);
+
+ else if (command == "sign")
+ MutateTxSign(tx, commandVal);
+
+ else if (command == "load")
+ RegisterLoad(commandVal);
+
+ else if (command == "set")
+ RegisterSet(commandVal);
+
+ else
+ throw runtime_error("unknown command");
+}
+
+static void OutputTxJSON(const CTransaction& tx)
+{
+ UniValue entry(UniValue::VOBJ);
+ TxToUniv(tx, 0, entry);
+
+ string jsonOutput = entry.write(4);
+ fprintf(stdout, "%s\n", jsonOutput.c_str());
+}
+
+static void OutputTxHex(const CTransaction& tx)
+{
+ string strHex = EncodeHexTx(tx);
+
+ fprintf(stdout, "%s\n", strHex.c_str());
+}
+
+static void OutputTx(const CTransaction& tx)
+{
+ if (GetBoolArg("-json", false))
+ OutputTxJSON(tx);
+ else
+ OutputTxHex(tx);
+}
+
+static int CommandLineRawTx(int argc, char* argv[])
+{
+ string strPrint;
+ int nRet = 0;
+ try {
+ // Skip switches
+ while (argc > 1 && IsSwitchChar(argv[1][0])) {
+ argc--;
+ argv++;
+ }
+
+ CTransaction txDecodeTmp;
+ int startArg;
+
+ if (!fCreateBlank) {
+ // require at least one param
+ if (argc < 2)
+ throw runtime_error("too few parameters");
+
+ // param: hex-encoded bitcoin transaction
+ string strHexTx(argv[1]);
+
+ if (!DecodeHexTx(txDecodeTmp, strHexTx))
+ throw runtime_error("invalid transaction encoding");
+
+ startArg = 2;
+ } else
+ startArg = 1;
+
+ CMutableTransaction tx(txDecodeTmp);
+
+ for (int i = startArg; i < argc; i++) {
+ string arg = argv[i];
+ string key, value;
+ size_t eqpos = arg.find('=');
+ if (eqpos == string::npos)
+ key = arg;
+ else {
+ key = arg.substr(0, eqpos);
+ value = arg.substr(eqpos + 1);
+ }
+
+ MutateTx(tx, key, value);
+ }
+
+ OutputTx(tx);
+ }
+
+ catch (boost::thread_interrupted) {
+ throw;
+ }
+ catch (std::exception& e) {
+ strPrint = string("error: ") + e.what();
+ nRet = EXIT_FAILURE;
+ }
+ catch (...) {
+ PrintExceptionContinue(NULL, "CommandLineRawTx()");
+ throw;
+ }
+
+ if (strPrint != "") {
+ fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
+ }
+ return nRet;
+}
+
+int main(int argc, char* argv[])
+{
+ SetupEnvironment();
+
+ try {
+ if(!AppInitRawTx(argc, argv))
+ return EXIT_FAILURE;
+ }
+ catch (std::exception& e) {
+ PrintExceptionContinue(&e, "AppInitRawTx()");
+ return EXIT_FAILURE;
+ } catch (...) {
+ PrintExceptionContinue(NULL, "AppInitRawTx()");
+ return EXIT_FAILURE;
+ }
+
+ int ret = EXIT_FAILURE;
+ try {
+ ret = CommandLineRawTx(argc, argv);
+ }
+ catch (std::exception& e) {
+ PrintExceptionContinue(&e, "CommandLineRawTx()");
+ } catch (...) {
+ PrintExceptionContinue(NULL, "CommandLineRawTx()");
+ }
+ return ret;
+}
+
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index b9097ea961..f32d4ed235 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -6,6 +6,7 @@
#include "chainparams.h"
#include "assert.h"
+#include "random.h"
#include "util.h"
#include <boost/assign/list_of.hpp>
@@ -13,88 +14,34 @@
using namespace std;
using namespace boost::assign;
+struct SeedSpec6 {
+ uint8_t addr[16];
+ uint16_t port;
+};
+
+#include "chainparamsseeds.h"
+
//
// Main network
//
-unsigned int pnSeed[] =
+// Convert the pnSeeds6 array into usable address objects.
+static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data, unsigned int count)
{
- 0x7e6a692e, 0x7d04d1a2, 0x6c0c17d9, 0xdb330ab9, 0xc649c7c6, 0x7895484d, 0x047109b0, 0xb90ca5bc,
- 0xd130805f, 0xbd074ea6, 0x578ff1c0, 0x286e09b0, 0xd4dcaf42, 0x529b6bb8, 0x635cc6c0, 0xedde892e,
- 0xa976d9c7, 0xea91a4b8, 0x03fa4eb2, 0x6ca9008d, 0xaf62c825, 0x93f3ba51, 0xc2c9efd5, 0x0ed5175e,
- 0x487028bc, 0x7297c225, 0x8af0c658, 0x2e57ba1f, 0xd0098abc, 0x46a8853e, 0xcc92dc3e, 0xeb6f1955,
- 0x8cce175e, 0x237281ae, 0x9d42795b, 0x4f4f0905, 0xc50151d0, 0xb1ba90c6, 0xaed7175e, 0x204de55b,
- 0x4bb03245, 0x932b28bc, 0x2dcce65b, 0xe2708abc, 0x1b08b8d5, 0x12a3dc5b, 0x8a884c90, 0xa386a8b8,
- 0x18e417c6, 0x2e709ac3, 0xeb62e925, 0x6f6503ae, 0x05d0814e, 0x8a9ac545, 0x946fd65e, 0x3f57495d,
- 0x4a29c658, 0xad454c90, 0x15340905, 0x4c3f3b25, 0x01fe19b9, 0x5620595b, 0x443c795b, 0x44f24ac8,
- 0x0442464e, 0xc8665882, 0xed3f3ec3, 0xf585bf5d, 0x5dd141da, 0xf93a084e, 0x1264dd52, 0x0711c658,
- 0xf12e7bbe, 0x5b02b740, 0x7d526dd5, 0x0cb04c90, 0x2abe1132, 0x61a39f58, 0x044a0618, 0xf3af7dce,
- 0xb994c96d, 0x361c5058, 0xca735d53, 0xeca743b0, 0xec790905, 0xc4d37845, 0xa1c4a2b2, 0x726fd453,
- 0x625cc6c0, 0x6c20132e, 0xb7aa0c79, 0xc6ed983d, 0x47e4cbc0, 0xa4ac75d4, 0xe2e59345, 0x4d784ad0,
- 0x18a5ec5e, 0x481cc85b, 0x7c6c2fd5, 0x5e4d6018, 0x5b4b6c18, 0xd99b4c90, 0xe63987dc, 0xb817bb25,
- 0x141cfeb2, 0x5f005058, 0x0d987f47, 0x242a496d, 0x3e519bc0, 0x02b2454b, 0xdfaf3dc6, 0x888128bc,
- 0x1165bb25, 0xabfeca5b, 0x2ef63540, 0x5773c7c6, 0x1280dd52, 0x8ebcacd9, 0x81c439c6, 0x39fcfa45,
- 0x62177d41, 0xc975ed62, 0x05cff476, 0xdabda743, 0xaa1ac24e, 0xe255a22e, 0x88aac705, 0xe707c658,
- 0xa9e94b5e, 0x2893484b, 0x99512705, 0xd63970ca, 0x45994f32, 0xe519a8ad, 0x92e25f5d, 0x8b84a9c1,
- 0x5eaa0a05, 0xa74de55b, 0xb090ff62, 0x5eee326c, 0xc331a679, 0xc1d9b72e, 0x0c6ab982, 0x7362bb25,
- 0x4cfedd42, 0x1e09a032, 0xa4c34c5e, 0x3777d9c7, 0x5edcf260, 0x3ce2b548, 0xd2ac0360, 0x2f80b992,
- 0x3e4cbb25, 0x3995e236, 0xd03977ae, 0x953cf054, 0x3c654ed0, 0x74024c90, 0xa14f1155, 0x14ce0125,
- 0xc15ebb6a, 0x2c08c452, 0xc7fd0652, 0x7604f8ce, 0xffb38332, 0xa4c2efd5, 0xe9614018, 0xab49e557,
- 0x1648c052, 0x36024047, 0x0e8cffad, 0x21918953, 0xb61f50ad, 0x9b406b59, 0xaf282218, 0x7f1d164e,
- 0x1f560da2, 0xe237be58, 0xbdeb1955, 0x6c0717d9, 0xdaf8ce62, 0x0f74246c, 0xdee95243, 0xf23f1a56,
- 0x61bdf867, 0xd254c854, 0xc4422e4e, 0xae0563c0, 0xbdb9a95f, 0xa9eb32c6, 0xd9943950, 0x116add52,
- 0x73a54c90, 0xb36b525e, 0xd734175e, 0x333d7f76, 0x51431bc6, 0x084ae5cf, 0xa60a236c, 0x5c67692e,
- 0x0177cf45, 0xa6683ac6, 0x7ff4ea47, 0x2192fab2, 0xa03a0f46, 0xfe3e39ae, 0x2cce5fc1, 0xc8a6c148,
- 0x96fb7e4c, 0x0a66c752, 0x6b4d2705, 0xeba0c118, 0x3ba0795b, 0x1dccd23e, 0x6912f3a2, 0x22f23c41,
- 0x65646b4a, 0x8b9f8705, 0xeb9b9a95, 0x79fe6b4e, 0x0536f447, 0x23224d61, 0x5d952ec6, 0x0cb4f736,
- 0xdc14be6d, 0xb24609b0, 0xd3f79b62, 0x6518c836, 0x83a3cf42, 0x9b641fb0, 0x17fef1c0, 0xd508cc82,
- 0x91a4369b, 0x39cb4a4c, 0xbbc9536c, 0xaf64c44a, 0x605eca50, 0x0c6a6805, 0xd07e9d4e, 0x78e6d3a2,
- 0x1b31eb6d, 0xaa01feb2, 0x4603c236, 0x1ecba3b6, 0x0effe336, 0xc3fdcb36, 0xc290036f, 0x4464692e,
- 0x1aca7589, 0x59a9e52e, 0x19aa7489, 0x2622c85e, 0xa598d318, 0x438ec345, 0xc79619b9, 0xaf570360,
- 0x5098e289, 0x36add862, 0x83c1a2b2, 0x969d0905, 0xcf3d156c, 0x49c1a445, 0xbd0b7562, 0x8fff1955,
- 0x1e51fe53, 0x28d6efd5, 0x2837cc62, 0x02f42d42, 0x070e3fb2, 0xbcb18705, 0x14a4e15b, 0x82096844,
- 0xcfcb1c2e, 0x37e27fc7, 0x07923748, 0x0c14bc2e, 0x26100905, 0xcb7cd93e, 0x3bc0d2c0, 0x97131b4c,
- 0x6f1e5c17, 0xa7939f43, 0xb7a0bf58, 0xafa83a47, 0xcbb83f32, 0x5f321cb0, 0x52d6c3c7, 0xdeac5bc7,
- 0x2cf310cc, 0x108a2bc3, 0x726fa14f, 0x85bad2cc, 0x459e4c90, 0x1a08b8d8, 0xcd7048c6, 0x6d5b4c90,
- 0xa66cfe7b, 0xad730905, 0xdaac5bc7, 0x8417fd9f, 0x41377432, 0x1f138632, 0x295a12b2, 0x7ac031b2,
- 0x3a87d295, 0xe219bc2e, 0xf485d295, 0x137b6405, 0xcfffd9ad, 0xafe20844, 0x32679a5f, 0xa431c644,
- 0x0e5fce8c, 0x305ef853, 0xad26ca32, 0xd9d21a54, 0xddd0d736, 0xc24ec0c7, 0x4aadcd5b, 0x49109852,
- 0x9d6b3ac6, 0xf0aa1e8b, 0xf1bfa343, 0x8a30c0ad, 0x260f93d4, 0x2339e760, 0x8869959f, 0xc207216c,
- 0x29453448, 0xb651ec36, 0x45496259, 0xa23d1bcc, 0xb39bcf43, 0xa1d29432, 0x3507c658, 0x4a88dd62,
- 0x27aff363, 0x7498ea6d, 0x4a6785d5, 0x5e6d47c2, 0x3baba542, 0x045a37ae, 0xa24dc0c7, 0xe981ea4d,
- 0xed6ce217, 0x857214c6, 0x6b6c0464, 0x5a4945b8, 0x12f24742, 0xf35f42ad, 0xfd0f5a4e, 0xfb081556,
- 0xb24b5861, 0x2e114146, 0xb7780905, 0x33bb0e48, 0x39e26556, 0xa794484d, 0x4225424d, 0x3003795b,
- 0x31c8cf44, 0xd65bad59, 0x127bc648, 0xf2bc4d4c, 0x0273dc50, 0x4572d736, 0x064bf653, 0xcdcd126c,
- 0x608281ae, 0x4d130087, 0x1016f725, 0xba185fc0, 0x16c1a84f, 0xfb697252, 0xa2942360, 0x53083b6c,
- 0x0583f1c0, 0x2d5a2441, 0xc172aa43, 0xcd11cf36, 0x7b14ed62, 0x5c94f1c0, 0x7c23132e, 0x39965a6f,
- 0x7890e24e, 0xa38ec447, 0xc187f1c0, 0xef80b647, 0xf20a7432, 0x7ad1d8d2, 0x869e2ec6, 0xccdb5c5d,
- 0x9d11f636, 0x2161bb25, 0x7599f889, 0x2265ecad, 0x0f4f0e55, 0x7d25854a, 0xf857e360, 0xf83f3d6c,
- 0x9cc93bb8, 0x02716857, 0x5dd8a177, 0x8adc6cd4, 0xe5613d46, 0x6a734f50, 0x2a5c3bae, 0x4a04c3d1,
- 0xe4613d46, 0x8426f4bc, 0x3e1b5fc0, 0x0d5a3c18, 0xd0f6d154, 0x21c7ff5e, 0xeb3f3d6c, 0x9da5edc0,
- 0x5d753b81, 0x0d8d53d4, 0x2613f018, 0x4443698d, 0x8ca1edcd, 0x10ed3f4e, 0x789b403a, 0x7b984a4b,
- 0x964ebc25, 0x7520ee60, 0x4f4828bc, 0x115c407d, 0x32dd0667, 0xa741715e, 0x1d3f3532, 0x817d1f56,
- 0x2f99a552, 0x6b2a5956, 0x8d4f4f05, 0xd23c1e17, 0x98993748, 0x2c92e536, 0x237ebdc3, 0xa762fb43,
- 0x32016b71, 0xd0e7cf79, 0x7d35bdd5, 0x53dac3d2, 0x31016b71, 0x7fb8f8ce, 0x9a38c232, 0xefaa42ad,
- 0x876b823d, 0x18175347, 0xdb46597d, 0xd2c168da, 0xcd6fe9dc, 0x45272e4e, 0x8d4bca5b, 0xa4043d47,
- 0xaab7aa47, 0x202881ae, 0xa4aef160, 0xecd7e6bc, 0x391359ad, 0xd8cc9318, 0xbbeee52e, 0x077067b0,
- 0xebd39d62, 0x0cedc547, 0x23d3e15e, 0xa5a81318, 0x179a32c6, 0xe4d3483d, 0x03680905, 0xe8018abc,
- 0xdde9ef5b, 0x438b8705, 0xb48224a0, 0xcbd69218, 0x9075795b, 0xc6411c3e, 0x03833f5c, 0xf33f8b5e,
- 0x495e464b, 0x83c8e65b, 0xac09cd25, 0xdaabc547, 0x7665a553, 0xc5263718, 0x2fd0c5cd, 0x22224d61,
- 0x3e954048, 0xfaa37557, 0x36dbc658, 0xa81453d0, 0x5a941f5d, 0xa598ea60, 0x65384ac6, 0x10aaa545,
- 0xaaab795b, 0xdda7024c, 0x0966f4c6, 0x68571c08, 0x8b40ee59, 0x33ac096c, 0x844b4c4b, 0xd392254d,
- 0xba4d5a46, 0x63029653, 0xf655f636, 0xbe4c4bb1, 0x45dad036, 0x204bc052, 0x06c3a2b2, 0xf31fba6a,
- 0xb21f09b0, 0x540d0751, 0xc7b46a57, 0x6a11795b, 0x3d514045, 0x0318aa6d, 0x30306ec3, 0x5c077432,
- 0x259ae46d, 0x82bbd35f, 0xae4222c0, 0x254415d4, 0xbd5f574b, 0xd8fd175e, 0x0a3f38c3, 0x2dce6bb8,
- 0xc201d058, 0x17fca5bc, 0xe8453cca, 0xd361f636, 0xa0d9edc0, 0x2f232e4e, 0x134e116c, 0x61ddc058,
- 0x05ba7283, 0xe1f7ed5b, 0x040ec452, 0x4b672e4e, 0xe4efa36d, 0x47dca52e, 0xe9332e4e, 0xa3acb992,
- 0x24714c90, 0xa8cc8632, 0x26b1ce6d, 0x264e53d4, 0xd3d2718c, 0x225534ad, 0xe289f3a2, 0x87341717,
- 0x9255ad4f, 0x184bbb25, 0x885c7abc, 0x3a6e9ac6, 0x1924185e, 0xb73d4c90, 0x946d807a, 0xa0d78e3f,
- 0x5a16bb25, 0xcb09795b, 0x8d0de657, 0x630b8b25, 0xe572c6cf, 0x2b3f1118, 0x4242a91f, 0x32990905,
- 0x058b0905, 0xe266fc60, 0xbe66c5b0, 0xcc98e46d, 0x698c943e, 0x44bd0cc3, 0x865c7abc, 0x771764d3,
- 0x4675d655, 0x354e4826, 0xb67ac152, 0xaeccf285, 0xea625b4e, 0xbcd6031f, 0x5e81eb18, 0x74b347ce,
- 0x3ca56ac1, 0x54ee4546, 0x38a8175e, 0xa3c21155, 0x2f01576d, 0x5d7ade50, 0xa003ae48, 0x2bc1d31f,
- 0x13f5094c, 0x7ab32648, 0x542e9fd5, 0x53136bc1, 0x7fdf51c0, 0x802197b2, 0xa2d2cc5b, 0x6b5f4bc0,
-};
+ // 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_t nOneWeek = 7*24*60*60;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ struct in6_addr ip;
+ memcpy(&ip, data[i].addr, sizeof(ip));
+ CAddress addr(CService(ip, data[i].port));
+ addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
+ vSeedsOut.push_back(addr);
+ }
+}
class CMainParams : public CChainParams {
public:
@@ -160,20 +107,7 @@ public:
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E);
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4);
- // 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_t 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);
- }
+ convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
fRequireRPCPassword = true;
fMiningRequiresPeers = true;
@@ -188,6 +122,7 @@ static CMainParams mainParams;
//
// Testnet (v3)
//
+
class CTestNetParams : public CMainParams {
public:
CTestNetParams() {
@@ -227,6 +162,8 @@ public:
base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF);
base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94);
+ convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
+
fRequireRPCPassword = true;
fMiningRequiresPeers = true;
fDefaultCheckMemPool = false;
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 19a9e72cc9..720e24c4a8 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -91,3 +91,7 @@ bool SelectBaseParamsFromCommandLine() {
}
return true;
}
+
+bool AreBaseParamsConfigured() {
+ return pCurrentBaseParams != NULL;
+}
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 4a3b268909..4398f69548 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -49,4 +49,10 @@ void SelectBaseParams(CBaseChainParams::Network network);
*/
bool SelectBaseParamsFromCommandLine();
+/**
+ * Return true if SelectBaseParamsFromCommandLine() has been called to select
+ * a network.
+ */
+bool AreBaseParamsConfigured();
+
#endif
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
new file mode 100644
index 0000000000..3f3278361e
--- /dev/null
+++ b/src/chainparamsseeds.h
@@ -0,0 +1,638 @@
+#ifndef H_CHAINPARAMSSEEDS
+#define H_CHAINPARAMSSEEDS
+// List of fixed seed nodes for the bitcoin network
+// AUTOGENERATED by contrib/devtools/generate-seeds.py
+
+// Each line contains a 16-byte IPv6 address and a port.
+// IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.
+static SeedSpec6 pnSeed6_main[] = {
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x69,0x6a,0x7e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x04,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x0c,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0a,0x33,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xc7,0x49,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x48,0x95,0x78}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x09,0x71,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa5,0x0c,0xb9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x80,0x30,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x4e,0x07,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0x8f,0x57}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x09,0x6e,0x28}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xaf,0xdc,0xd4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0x9b,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xc6,0x5c,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x89,0xde,0xed}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xd9,0x76,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0xa4,0x91,0xea}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x4e,0xfa,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x00,0xa9,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc8,0x62,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xba,0xf3,0x93}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xef,0xc9,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0xd5,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x28,0x70,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xc2,0x97,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0xf0,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x57,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x09,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xa8,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xdc,0x92,0xcc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0x6f,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0xce,0x8c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x81,0x72,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x42,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x4f,0x4f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x51,0x01,0xc5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x90,0xba,0xb1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0xd7,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe5,0x4d,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x32,0xb0,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x28,0x2b,0x93}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe6,0xcc,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x70,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb8,0x08,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdc,0xa3,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x88,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0xa8,0x86,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x17,0xe4,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0x70,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xe9,0x62,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x03,0x65,0x6f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x81,0xd0,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xc5,0x9a,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xd6,0x6f,0x94}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x49,0x57,0x3f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0x29,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x45,0xad}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x34,0x15}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x3b,0x3f,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0xfe,0x01}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x59,0x20,0x56}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x3c,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x4a,0xf2,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x46,0x42,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0x58,0x66,0xc8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x3e,0x3f,0xed}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbf,0x85,0xf5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0x41,0xd1,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x08,0x3a,0xf9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x64,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0x11,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x7b,0x2e,0xf1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xb7,0x02,0x5b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x6d,0x52,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0xb0,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x11,0xbe,0x2a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x9f,0xa3,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x06,0x4a,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7d,0xaf,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc9,0x94,0xb9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x50,0x1c,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x5d,0x73,0xca}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x43,0xa7,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x79,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x78,0xd3,0xc4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa2,0xc4,0xa1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd4,0x6f,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xc6,0x5c,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x20,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x0c,0xaa,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x98,0xed,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcb,0xe4,0x47}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x75,0xac,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x93,0xe5,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4a,0x78,0x4d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xec,0xa5,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc8,0x1c,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x2f,0x6c,0x7c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x60,0x4d,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x6c,0x4b,0x5b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x9b,0xd9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x87,0x39,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x17,0xb8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x1c,0x14}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x50,0x00,0x5f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x7f,0x98,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x49,0x2a,0x24}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x9b,0x51,0x3e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x45,0xb2,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3d,0xaf,0xdf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x28,0x81,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x65,0x11}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xca,0xfe,0xab}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x35,0xf6,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xc7,0x73,0x57}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xac,0xbc,0x8e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x39,0xc4,0x81}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xfa,0xfc,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x7d,0x17,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xed,0x75,0xc9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xf4,0xcf,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa7,0xbd,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xc2,0x1a,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa2,0x55,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0xaa,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0x07,0xe7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x4b,0xe9,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x48,0x93,0x28}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0x51,0x99}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x70,0x39,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4f,0x99,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xa8,0x19,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5f,0xe2,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xa9,0x84,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x0a,0xaa,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe5,0x4d,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xff,0x90,0xb0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x32,0xee,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xa6,0x31,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xb7,0xd9,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0xb9,0x6a,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x62,0x73}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xdd,0xfe,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xa0,0x09,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x4c,0xc3,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xd9,0x77,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xf2,0xdc,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xb5,0xe2,0x3c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x03,0xac,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0x80,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x4c,0x3e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xe2,0x95,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x77,0x39,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf0,0x3c,0x95}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4e,0x65,0x3c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x02,0x74}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x11,0x4f,0xa1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x01,0xce,0x14}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xbb,0x5e,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc4,0x08,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x06,0xfd,0xc7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xf8,0x04,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x83,0xb3,0xff}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xef,0xc2,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x40,0x61,0xe9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe5,0x49,0xab}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc0,0x48,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x40,0x02,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0x8c,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x89,0x91,0x21}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x50,0x1f,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x6b,0x40,0x9b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x22,0x28,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x16,0x1d,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x0d,0x56,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xbe,0x37,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xeb,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x07,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xce,0xf8,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x24,0x74,0x0f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x52,0xe9,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x1a,0x3f,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xf8,0xbd,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc8,0x54,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x42,0xc4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x63,0x05,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa9,0xb9,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x32,0xeb,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x39,0x94,0xd9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6a,0x11}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0xa5,0x73}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x52,0x6b,0xb3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0x34,0xd7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x7f,0x3d,0x33}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x1b,0x43,0x51}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xe5,0x4a,0x08}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x23,0x0a,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x69,0x67,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xcf,0x77,0x01}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3a,0x68,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xea,0xf4,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfa,0x92,0x21}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x0f,0x3a,0xa0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x39,0x3e,0xfe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x5f,0xce,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xc1,0xa6,0xc8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x7e,0xfb,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0x4d,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xc1,0xa0,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0xa0,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0xcc,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x12,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x3c,0xf2,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x6b,0x64,0x65}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x87,0x9f,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0x9a,0x9b,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6b,0xfe,0x79}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xf4,0x36,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x4d,0x22,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x2e,0x95,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf7,0xb4,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xbe,0x14,0xdc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x09,0x46,0xb2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x9b,0xf7,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xc8,0x18,0x65}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xcf,0xa3,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x1f,0x64,0x9b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0xfe,0x17}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0xcc,0x08,0xd5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x36,0xa4,0x91}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x4a,0xcb,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x53,0xc9,0xbb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xc4,0x64,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xca,0x5e,0x60}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x68,0x6a,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x9d,0x7e,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd3,0xe6,0x78}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xeb,0x31,0x1b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x01,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xc2,0x03,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb6,0xa3,0xcb,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xe3,0xff,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xcb,0xfd,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x03,0x90,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x69,0x64,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x75,0xca,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa9,0x59}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x74,0xaa,0x19}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc8,0x22,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd3,0x98,0xa5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xc3,0x8e,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x96,0xc7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x03,0x57,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x98,0x50}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xd8,0xad,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa2,0xc1,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x9d,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x15,0x3d,0xcf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xa4,0xc1,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x75,0x0b,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xff,0x8f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfe,0x51,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xef,0xd6,0x28}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xcc,0x37,0x28}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x2d,0xf4,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3f,0x0e,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x87,0xb1,0xbc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe1,0xa4,0x14}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x68,0x09,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcb,0xcf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0xe2,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x37,0x92,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x14,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x10,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd9,0x7c,0xcb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xd2,0xc0,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x1b,0x13,0x97}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x5c,0x1e,0x6f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x9f,0x93,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xbf,0xa0,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x3a,0xa8,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x3f,0xb8,0xcb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x1c,0x32,0x5f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc3,0xd6,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x5b,0xac,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x10,0xf3,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x2b,0x8a,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa1,0x6f,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0xd2,0xba,0x85}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x9e,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xb8,0x08,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x48,0x70,0xcd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x5b,0x6d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7b,0xfe,0x6c,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x73,0xad}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x5b,0xac,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x17,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x37,0x41}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x86,0x13,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x12,0x5a,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x31,0xc0,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0x87,0x3a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x19,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xd2,0x85,0xf4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x64,0x7b,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd9,0xff,0xcf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x08,0xe2,0xaf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0x67,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc6,0x31,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8c,0xce,0x5f,0x0e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf8,0x5e,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xca,0x26,0xad}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x1a,0xd2,0xd9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xd7,0xd0,0xdd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc0,0x4e,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xcd,0xad,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x98,0x10,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3a,0x6b,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x1e,0xaa,0xf0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xa3,0xbf,0xf1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xc0,0x30,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x93,0x0f,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xe7,0x39,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x95,0x69,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x21,0x07,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x34,0x45,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xec,0x51,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x62,0x49,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x1b,0x3d,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xcf,0x9b,0xb3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x94,0xd2,0xa1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0x07,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xdd,0x88,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xf3,0xaf,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xea,0x98,0x74}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x85,0x67,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x47,0x6d,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xa5,0xab,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x37,0x5a,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc0,0x4d,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xea,0x81,0xe9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe2,0x6c,0xed}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x14,0x72,0x85}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x64,0x04,0x6c,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x45,0x49,0x5a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x47,0xf2,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x42,0x5f,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x5a,0x0f,0xfd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x15,0x08,0xfb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x58,0x4b,0xb2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x41,0x11,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x78,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0e,0xbb,0x33}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x65,0xe2,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x48,0x94,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x42,0x25,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x03,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xcf,0xc8,0x31}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xad,0x5b,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xc6,0x7b,0x12}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x4d,0xbc,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xdc,0x73,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xd7,0x72,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf6,0x4b,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x12,0xcd,0xcd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x81,0x82,0x60}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x00,0x13,0x4d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xf7,0x16,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5f,0x18,0xba}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xa8,0xc1,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x72,0x69,0xfb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x23,0x94,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3b,0x08,0x53}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0x83,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x24,0x5a,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xaa,0x72,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xcf,0x11,0xcd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0xed,0x14,0x7b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0x94,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x23,0x7c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x96,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0xe2,0x90,0x78}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc4,0x8e,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xf1,0x87,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xb6,0x80,0xef}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x0a,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xd8,0xd1,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x2e,0x9e,0x86}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5c,0xdb,0xcc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf6,0x11,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x61,0x21}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xf8,0x99,0x75}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xec,0x65,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0e,0x4f,0x0f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x85,0x25,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xe3,0x57,0xf8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x3f,0xf8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x3b,0xc9,0x9c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x68,0x71,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xa1,0xd8,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x6c,0xdc,0x8a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3d,0x61,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x4f,0x73,0x6a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x3b,0x5c,0x2a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xc3,0x04,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x3d,0x61,0xe4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xf4,0x26,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x5f,0x1b,0x3e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x3c,0x5a,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd1,0xf6,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xff,0xc7,0x21}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3d,0x3f,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xed,0xa5,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x3b,0x75,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x53,0x8d,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xf0,0x13,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x69,0x43,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcd,0xed,0xa1,0x8c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x3f,0xed,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x40,0x9b,0x78}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x4a,0x98,0x7b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbc,0x4e,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xee,0x20,0x75}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x28,0x48,0x4f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0x40,0x5c,0x11}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x06,0xdd,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x71,0x41,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x35,0x3f,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x1f,0x7d,0x81}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa5,0x99,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x59,0x2a,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x4f,0x4f,0x8d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1e,0x3c,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x37,0x99,0x98}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xe5,0x92,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xbd,0x7e,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xfb,0x62,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x6b,0x01,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0xcf,0xe7,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xbd,0x35,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd2,0xc3,0xda,0x53}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x6b,0x01,0x31}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xf8,0xb8,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xc2,0x38,0x9a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x42,0xaa,0xef}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x82,0x6b,0x87}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x53,0x17,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0x59,0x46,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0x68,0xc1,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xe9,0x6f,0xcd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x27,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xca,0x4b,0x8d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x3d,0x04,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xaa,0xb7,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x81,0x28,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xf1,0xae,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe6,0xd7,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x59,0x13,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x93,0xcc,0xd8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x67,0x70,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x9d,0xd3,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc5,0xed,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xe1,0xd3,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x13,0xa8,0xa5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x32,0x9a,0x17}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x48,0xd3,0xe4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x68,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x01,0xe8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xef,0xe9,0xdd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x87,0x8b,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x24,0x82,0xb4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x92,0xd6,0xcb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x75,0x90}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x1c,0x41,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3f,0x83,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x8b,0x3f,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x46,0x5e,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe6,0xc8,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xcd,0x09,0xac}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xc5,0xab,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa5,0x65,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x37,0x26,0xc5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcd,0xc5,0xd0,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x4d,0x22,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x40,0x95,0x3e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x75,0xa3,0xfa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc6,0xdb,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x53,0x14,0xa8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x1f,0x94,0x5a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xea,0x98,0xa5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x4a,0x38,0x65}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xa5,0xaa,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0xab,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x02,0xa7,0xdd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xf4,0x66,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x1c,0x57,0x68}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xee,0x40,0x8b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x09,0xac,0x33}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x4c,0x4b,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x25,0x92,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x5a,0x4d,0xba}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x96,0x02,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf6,0x55,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x4b,0x4c,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xd0,0xda,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc0,0x4b,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xa2,0xc3,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xba,0x1f,0xf3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x09,0x1f,0xb2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0d,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x6a,0xb4,0xc7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x11,0x6a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x51,0x3d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xaa,0x18,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x6e,0x30,0x30}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x74,0x07,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x9a,0x25}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0xbb,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x22,0x42,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x15,0x44,0x25}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x57,0x5f,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0xfd,0xd8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x6b,0xce,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x01,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xa5,0xfc,0x17}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x3c,0x45,0xe8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf6,0x61,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xed,0xd9,0xa0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x23,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x11,0x4e,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xc0,0xdd,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0xba,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xed,0xf7,0xe1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc4,0x0e,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x67,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xa3,0xef,0xe4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa5,0xdc,0x47}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x2e,0x33,0xe9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x92,0xb9,0xac,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x71,0x24}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x86,0xcc,0xa8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xce,0xb1,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x53,0x4e,0x26}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8c,0x71,0xd2,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x34,0x55,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0x89,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x17,0x34,0x87}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xad,0x55,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x4b,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7a,0x5c,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x9a,0x6e,0x3a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x18,0x24,0x19}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x4c,0x3d,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x80,0x6d,0x94}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8e,0xd7,0xa0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbb,0x16,0x5a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0x09,0xcb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe6,0x0d,0x8d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8b,0x0b,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xc6,0x72,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x11,0x3f,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xa9,0x42,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x99,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x09,0x8b,0x05}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xfc,0x66,0xe2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xc5,0x66,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe4,0x98,0xcc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x94,0x8c,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x0c,0xbd,0x44}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7a,0x5c,0x86}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x64,0x17,0x77}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x75,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x48,0x4e,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x7a,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x85,0xf2,0xcc,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x5b,0x62,0xea}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x03,0xd6,0xbc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xeb,0x81,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x47,0xb3,0x74}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6a,0xa5,0x3c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x45,0xee,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x17,0xa8,0x38}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x11,0xc2,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x57,0x01,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xde,0x7a,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xae,0x03,0xa0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd3,0xc1,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x09,0xf5,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x26,0xb3,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9f,0x2e,0x54}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6b,0x13,0x53}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x51,0xdf,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x97,0x21,0x80}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xcc,0xd2,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x4b,0x5f,0x6b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xae,0x94,0xd5,0xc2,0x72,0x24}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0xb9,0x5b,0x63,0x1d,0x94,0xe2,0xed,0xec,0xa1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xe6,0xdf,0xeb,0xe5,0xc5,0x9a,0x87,0x5e,0x22}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0x71,0xa2,0x43,0x2a,0xe6,0x6c,0x8e,0xe4,0x7b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0xf4,0x0b,0x4c,0x52,0xd5,0x16,0xcf,0xf5,0x06}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0xff,0x33,0x38,0xbb,0x43,0x08,0x8d,0x95,0x9e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x64,0x1b,0x1f,0x8f,0x87,0x18,0x7d,0xa3,0x2b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0xda,0x83,0x67,0x90,0x6f,0x46,0x10,0xdb,0x53}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0x1b,0x22,0x8c,0x89,0x60,0xbf,0xca,0x88,0xa1}, 7033},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xe3,0x5b,0x75,0x10,0x46,0x5e,0xf0,0x99,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xba,0x44,0x94,0x9d,0xf5,0xc0,0xaa,0xcd,0x4a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0x64,0xce,0x6d,0xd4,0xfb,0xa7,0x6b,0x60,0xb5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x8f,0x0b,0x72,0xc9,0xf1,0xde,0x62,0xd4,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x25,0x5c,0xbc,0x34,0xe8,0x9f,0xe4,0x7c,0x90,0x93}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe0,0xa2,0x72,0xef,0xfa,0x7b,0x88,0x95,0x8b,0x9c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0x69,0xc5,0x40,0xa7,0x95,0xbb,0x25,0xc1,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x46,0xa3,0xd9,0x84,0x08,0xc8,0x7f,0xd3,0xeb,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0xc4,0xd2,0x4f,0x74,0x99,0xb3,0x8c,0xe8,0x25}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x9d,0xb8,0xf8,0x4c,0x4b,0x9c,0xc3,0x9c,0xc6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0x1d,0x28,0x9f,0xd6,0x28,0x28,0x22,0x4f,0x7a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x36,0xa1,0xc1,0xd6,0x64,0x43,0xfb,0xb3,0xe7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x06,0x4e,0x64,0xbc,0x5e,0x1a,0x8a,0x71,0x97}, 8444}
+};
+
+static SeedSpec6 pnSeed6_test[] = {
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xcb,0x26,0x31,0xba,0x48,0x51,0x31,0x39,0x0d}, 18333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333}
+};
+#endif
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 4cab11db3d..717f0b90fe 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -51,11 +51,12 @@ namespace Checkpoints {
(225430, uint256("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932"))
(250000, uint256("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214"))
(279000, uint256("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40"))
+ (295000, uint256("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983"))
;
static const CCheckpointData data = {
&mapCheckpoints,
- 1389047471, // * UNIX timestamp of last checkpoint block
- 30549816, // * total number of transactions between genesis and last checkpoint
+ 1397080064, // * UNIX timestamp of last checkpoint block
+ 36544669, // * total number of transactions between genesis and last checkpoint
// (the tx=... number in the SetBestChain debug.log lines)
60000.0 // * estimated number of transactions per day after checkpoint
};
diff --git a/src/coins.cpp b/src/coins.cpp
index 13a4ea95cd..fe40911db7 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -4,6 +4,8 @@
#include "coins.h"
+#include "random.h"
+
#include <assert.h>
// calculate number of bytes for the bitmask, and its number of non-zero bytes
@@ -69,6 +71,8 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
+CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
+
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { }
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
@@ -84,8 +88,8 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) {
}
CCoinsMap::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) {
- CCoinsMap::iterator it = cacheCoins.lower_bound(txid);
- if (it != cacheCoins.end() && it->first == txid)
+ CCoinsMap::iterator it = cacheCoins.find(txid);
+ if (it != cacheCoins.end())
return it;
CCoins tmp;
if (!base->GetCoins(txid,tmp))
@@ -107,7 +111,12 @@ bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) {
}
bool CCoinsViewCache::HaveCoins(const uint256 &txid) {
- return FetchCoins(txid) != cacheCoins.end();
+ CCoinsMap::iterator it = FetchCoins(txid);
+ // We're using vtx.empty() instead of IsPruned here for performance reasons,
+ // as we only care about the case where an transaction was replaced entirely
+ // in a reorganization (which wipes vout entirely, as opposed to spending
+ // which just cleans individual outputs).
+ return (it != cacheCoins.end() && !it->second.vout.empty());
}
uint256 CCoinsViewCache::GetBestBlock() {
diff --git a/src/coins.h b/src/coins.h
index c57a5ec722..ff60288163 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -13,6 +13,7 @@
#include <stdint.h>
#include <boost/foreach.hpp>
+#include <boost/unordered_map.hpp>
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
*
@@ -239,7 +240,22 @@ public:
}
};
-typedef std::map<uint256,CCoins> CCoinsMap;
+class CCoinsKeyHasher
+{
+private:
+ uint256 salt;
+
+public:
+ CCoinsKeyHasher();
+ // This *must* return size_t. With Boost 1.46 on 32-bit systems the
+ // unordered_map will behave unpredictably if the custom hasher returns a
+ // uint64_t, resulting in failures when syncing the chain (#4634).
+ size_t operator()(const uint256& key) const {
+ return key.GetHash(salt);
+ }
+};
+
+typedef boost::unordered_map<uint256, CCoins, CCoinsKeyHasher> CCoinsMap;
struct CCoinsStats
{
diff --git a/src/compat.h b/src/compat.h
index 8fbafb6cce..52c7817130 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
+// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -59,19 +59,4 @@ typedef u_int SOCKET;
#define SOCKET_ERROR -1
#endif
-inline int myclosesocket(SOCKET& hSocket)
-{
- if (hSocket == INVALID_SOCKET)
- return WSAENOTSOCK;
-#ifdef WIN32
- int ret = closesocket(hSocket);
-#else
- int ret = close(hSocket);
-#endif
- hSocket = INVALID_SOCKET;
- return ret;
-}
-#define closesocket(s) myclosesocket(s)
-
-
-#endif
+#endif // _BITCOIN_COMPAT_H
diff --git a/src/compat/glibcxx_compat.cpp b/src/compat/glibcxx_compat.cpp
index 417166aeda..cbe059735b 100644
--- a/src/compat/glibcxx_compat.cpp
+++ b/src/compat/glibcxx_compat.cpp
@@ -64,6 +64,8 @@ template istream& istream::_M_extract(unsigned short&);
out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { }
+length_error::~length_error() _GLIBCXX_USE_NOEXCEPT { }
+
// Used with permission.
// See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d
diff --git a/src/core.cpp b/src/core.cpp
index b56994ecf3..149b3532a1 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -124,22 +124,6 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
return *this;
}
-bool CTransaction::IsEquivalentTo(const CTransaction& tx) const
-{
- if (nVersion != tx.nVersion ||
- nLockTime != tx.nLockTime ||
- vin.size() != tx.vin.size() ||
- vout != tx.vout)
- return false;
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != tx.vin[i].nSequence ||
- vin[i].prevout != tx.vin[i].prevout)
- return false;
- }
- return true;
-}
-
int64_t CTransaction::GetValueOut() const
{
int64_t nValueOut = 0;
diff --git a/src/core.h b/src/core.h
index 0387336c98..fb64e6c08e 100644
--- a/src/core.h
+++ b/src/core.h
@@ -255,9 +255,6 @@ public:
return hash;
}
- // True if only scriptSigs are different
- bool IsEquivalentTo(const CTransaction& tx) const;
-
// Return sum of txouts.
int64_t GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
diff --git a/src/core_io.h b/src/core_io.h
new file mode 100644
index 0000000000..adf74cce32
--- /dev/null
+++ b/src/core_io.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2009-2014 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_IO_H__
+#define __BITCOIN_CORE_IO_H__
+
+#include <string>
+#include <vector>
+
+class uint256;
+class CScript;
+class CTransaction;
+class UniValue;
+
+// core_read.cpp
+extern CScript ParseScript(std::string s);
+extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
+extern uint256 ParseHashUV(const UniValue& v, const std::string& strName);
+extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
+
+// core_write.cpp
+extern std::string EncodeHexTx(const CTransaction& tx);
+extern void ScriptPubKeyToUniv(const CScript& scriptPubKey,
+ UniValue& out, bool fIncludeHex);
+extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
+
+#endif // __BITCOIN_CORE_IO_H__
diff --git a/src/core_read.cpp b/src/core_read.cpp
new file mode 100644
index 0000000000..593eb2d035
--- /dev/null
+++ b/src/core_read.cpp
@@ -0,0 +1,129 @@
+// Copyright (c) 2009-2014 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_io.h"
+#include "core.h"
+#include "serialize.h"
+#include "script.h"
+#include "util.h"
+
+#include <boost/assign/list_of.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include "univalue/univalue.h"
+
+using namespace std;
+using namespace boost;
+using namespace boost::algorithm;
+
+CScript ParseScript(std::string s)
+{
+ CScript result;
+
+ static map<string, opcodetype> mapOpNames;
+
+ if (mapOpNames.empty())
+ {
+ for (int op = 0; op <= OP_NOP10; op++)
+ {
+ // Allow OP_RESERVED to get into mapOpNames
+ if (op < OP_NOP && op != OP_RESERVED)
+ continue;
+
+ const char* name = GetOpName((opcodetype)op);
+ if (strcmp(name, "OP_UNKNOWN") == 0)
+ continue;
+ string strName(name);
+ mapOpNames[strName] = (opcodetype)op;
+ // Convenience: OP_ADD and just ADD are both recognized:
+ replace_first(strName, "OP_", "");
+ mapOpNames[strName] = (opcodetype)op;
+ }
+ }
+
+ vector<string> words;
+ split(words, s, is_any_of(" \t\n"), token_compress_on);
+
+ for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
+ {
+ if (w->empty())
+ {
+ // Empty string, ignore. (boost::split given '' will return one word)
+ }
+ else if (all(*w, is_digit()) ||
+ (starts_with(*w, "-") && all(string(w->begin()+1, w->end()), is_digit())))
+ {
+ // Number
+ int64_t n = atoi64(*w);
+ result << n;
+ }
+ else if (starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end())))
+ {
+ // Raw hex data, inserted NOT pushed onto stack:
+ std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
+ result.insert(result.end(), raw.begin(), raw.end());
+ }
+ else if (w->size() >= 2 && starts_with(*w, "'") && ends_with(*w, "'"))
+ {
+ // Single-quoted string, pushed as data. NOTE: this is poor-man's
+ // parsing, spaces/tabs/newlines in single-quoted strings won't work.
+ std::vector<unsigned char> value(w->begin()+1, w->end()-1);
+ result << value;
+ }
+ else if (mapOpNames.count(*w))
+ {
+ // opcode, e.g. OP_ADD or ADD:
+ result << mapOpNames[*w];
+ }
+ else
+ {
+ throw runtime_error("script parse error");
+ }
+ }
+
+ return result;
+}
+
+bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
+{
+ if (!IsHex(strHexTx))
+ return false;
+
+ vector<unsigned char> txData(ParseHex(strHexTx));
+ CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+ try {
+ ssData >> tx;
+ }
+ catch (std::exception &e) {
+ return false;
+ }
+
+ return true;
+}
+
+uint256 ParseHashUV(const UniValue& v, const string& strName)
+{
+ string strHex;
+ if (v.isStr())
+ strHex = v.getValStr();
+ if (!IsHex(strHex)) // Note: IsHex("") is false
+ throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
+
+ uint256 result;
+ result.SetHex(strHex);
+ return result;
+}
+
+vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
+{
+ string strHex;
+ if (v.isStr())
+ strHex = v.getValStr();
+ if (!IsHex(strHex))
+ throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
+ return ParseHex(strHex);
+}
+
diff --git a/src/core_write.cpp b/src/core_write.cpp
new file mode 100644
index 0000000000..37dd69f7b8
--- /dev/null
+++ b/src/core_write.cpp
@@ -0,0 +1,91 @@
+// Copyright (c) 2009-2014 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_io.h"
+#include "univalue/univalue.h"
+#include "script.h"
+#include "core.h"
+#include "serialize.h"
+#include "util.h"
+#include "base58.h"
+
+using namespace std;
+
+string EncodeHexTx(const CTransaction& tx)
+{
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << tx;
+ return HexStr(ssTx.begin(), ssTx.end());
+}
+
+void ScriptPubKeyToUniv(const CScript& scriptPubKey,
+ UniValue& out, bool fIncludeHex)
+{
+ txnouttype type;
+ vector<CTxDestination> addresses;
+ int nRequired;
+
+ out.pushKV("asm", scriptPubKey.ToString());
+ if (fIncludeHex)
+ out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
+
+ if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
+ out.pushKV("type", GetTxnOutputType(type));
+ return;
+ }
+
+ out.pushKV("reqSigs", nRequired);
+ out.pushKV("type", GetTxnOutputType(type));
+
+ UniValue a(UniValue::VARR);
+ BOOST_FOREACH(const CTxDestination& addr, addresses)
+ a.push_back(CBitcoinAddress(addr).ToString());
+ out.pushKV("addresses", a);
+}
+
+void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
+{
+ entry.pushKV("txid", tx.GetHash().GetHex());
+ entry.pushKV("version", tx.nVersion);
+ entry.pushKV("locktime", (int64_t)tx.nLockTime);
+
+ UniValue vin(UniValue::VARR);
+ BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ UniValue in(UniValue::VOBJ);
+ if (tx.IsCoinBase())
+ in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
+ else {
+ in.pushKV("txid", txin.prevout.hash.GetHex());
+ in.pushKV("vout", (int64_t)txin.prevout.n);
+ UniValue o(UniValue::VOBJ);
+ o.pushKV("asm", txin.scriptSig.ToString());
+ o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
+ in.pushKV("scriptSig", o);
+ }
+ in.pushKV("sequence", (int64_t)txin.nSequence);
+ vin.push_back(in);
+ }
+ entry.pushKV("vin", vin);
+
+ UniValue vout(UniValue::VARR);
+ for (unsigned int i = 0; i < tx.vout.size(); i++) {
+ const CTxOut& txout = tx.vout[i];
+
+ UniValue out(UniValue::VOBJ);
+
+ UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue));
+ out.pushKV("value", outValue);
+ out.pushKV("n", (int64_t)i);
+
+ UniValue o(UniValue::VOBJ);
+ ScriptPubKeyToUniv(txout.scriptPubKey, o, true);
+ out.pushKV("scriptPubKey", o);
+ vout.push_back(out);
+ }
+ entry.pushKV("vout", vout);
+
+ if (hashBlock != 0)
+ entry.pushKV("blockhash", hashBlock.GetHex());
+}
+
diff --git a/src/init.cpp b/src/init.cpp
index 3f068da89f..8ae228bbbe 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -58,7 +58,8 @@ CWallet* pwalletMain;
enum BindFlags {
BF_NONE = 0,
BF_EXPLICIT = (1U << 0),
- BF_REPORT_ERROR = (1U << 1)
+ BF_REPORT_ERROR = (1U << 1),
+ BF_WHITELIST = (1U << 2),
};
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
@@ -126,12 +127,14 @@ void Shutdown()
StopNode();
UnregisterNodeSignals(GetNodeSignals());
- boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_fileout = CAutoFile(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
- if (est_fileout)
- mempool.WriteFeeEstimates(est_fileout);
- else
- LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
+ {
+ boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
+ if (est_fileout)
+ mempool.WriteFeeEstimates(est_fileout);
+ else
+ LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
+ }
{
LOCK(cs_main);
@@ -178,13 +181,13 @@ void HandleSIGHUP(int)
bool static InitError(const std::string &str)
{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::NOSHOWGUI);
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
return false;
}
bool static InitWarning(const std::string &str)
{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING | CClientUIInterface::NOSHOWGUI);
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
return true;
}
@@ -192,7 +195,7 @@ bool static Bind(const CService &addr, unsigned int flags) {
if (!(flags & BF_EXPLICIT) && IsLimited(addr))
return false;
std::string strError;
- if (!BindListenPort(addr, strError)) {
+ if (!BindListenPort(addr, strError, flags & BF_WHITELIST)) {
if (flags & BF_REPORT_ERROR)
return InitError(strError);
return false;
@@ -223,6 +226,9 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n";
strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n";
+#if !defined(WIN32)
+ strUsage += " -sysperms " + _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)") + "\n";
+#endif
strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n";
strUsage += "\n" + _("Connection options:") + "\n";
@@ -233,14 +239,16 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n";
strUsage += " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n";
strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)") + "\n";
- strUsage += " -dnsseed " + _("Find peers using DNS lookup (default: 1 unless -connect)") + "\n";
+ strUsage += " -dnsseed " + _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)") + "\n";
strUsage += " -externalip=<ip> " + _("Specify your own public address") + "\n";
+ strUsage += " -forcednsseed " + _("Always query for peer addresses via DNS lookup (default: 0)") + "\n";
strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n";
strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\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";
strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n";
strUsage += " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4, IPv6 or Tor)") + "\n";
+ strUsage += " -permitbaremultisig " + _("Relay non-P2SH multisig (default: 1)") + "\n";
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS5 proxy") + "\n";
strUsage += " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n";
@@ -252,6 +260,9 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n";
#endif
#endif
+ strUsage += " -whitebind=<addr> " + _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6") + "\n";
+ strUsage += " -whitelist=<netmask> " + _("Whitelist peers connecting from the given netmask or ip. Can be specified multiple times.") + "\n";
+ strUsage += " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway") + "\n";
#ifdef ENABLE_WALLET
strUsage += "\n" + _("Wallet options:") + "\n";
@@ -268,14 +279,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
- strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n";
+ strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + "\n";
strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n";
#endif
strUsage += "\n" + _("Debugging/Testing options:") + "\n";
if (GetBoolArg("-help-debug", false))
{
- strUsage += " -benchmark " + _("Show benchmark information (default: 0)") + "\n";
strUsage += " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n";
strUsage += " -dblogsize=<n> " + _("Flush database activity from memory pool to disk log every <n> megabytes (default: 100)") + "\n";
strUsage += " -disablesafemode " + _("Disable safemode, override a real safe mode event (default: 0)") + "\n";
@@ -288,7 +298,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n";
strUsage += " " + _("If <category> is not supplied, output all debugging information.") + "\n";
strUsage += " " + _("<category> can be:");
- strUsage += " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
+ strUsage += " addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below
if (mode == HMM_BITCOIN_QT)
strUsage += ", qt";
strUsage += ".\n";
@@ -481,7 +491,15 @@ bool AppInit2(boost::thread_group& threadGroup)
}
#endif
#ifndef WIN32
- umask(077);
+
+ if (GetBoolArg("-sysperms", false)) {
+#ifdef ENABLE_WALLET
+ if (!GetBoolArg("-disablewallet", false))
+ return InitError("Error: -sysperms is not allowed in combination with enabled wallet functionality");
+#endif
+ } else {
+ umask(077);
+ }
// Clean shutdown on SIGTERM
struct sigaction sa;
@@ -506,11 +524,11 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 2: parameter interactions
- if (mapArgs.count("-bind")) {
+ if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
// when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
if (SoftSetBoolArg("-listen", true))
- LogPrintf("AppInit2 : parameter interaction: -bind set -> setting -listen=1\n");
+ LogPrintf("AppInit2 : parameter interaction: -bind or -whitebind set -> setting -listen=1\n");
}
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) {
@@ -554,7 +572,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
// Make sure enough file descriptors are available
- int nBind = std::max((int)mapArgs.count("-bind"), 1);
+ int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
nMaxConnections = GetArg("-maxconnections", 125);
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
@@ -581,7 +599,9 @@ bool AppInit2(boost::thread_group& threadGroup)
if (GetBoolArg("-tor", false))
return InitError(_("Error: Unsupported argument -tor found, use -onion."));
- fBenchmark = GetBoolArg("-benchmark", false);
+ if (GetBoolArg("-benchmark", false))
+ InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench."));
+
// Checkmempool defaults to true in regtest mode
mempool.setSanityCheck(GetBoolArg("-checkmempool", Params().DefaultCheckMemPool()));
Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
@@ -659,7 +679,10 @@ bool AppInit2(boost::thread_group& threadGroup)
bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
std::string strWalletFile = GetArg("-wallet", "wallet.dat");
-#endif
+#endif // ENABLE_WALLET
+
+ fIsBareMultisigStd = GetArg("-permitbaremultisig", true);
+
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Sanity check
if (!InitSanityCheck())
@@ -771,6 +794,15 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
+ if (mapArgs.count("-whitelist")) {
+ BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
+ CSubNet subnet(net);
+ if (!subnet.IsValid())
+ return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
+ CNode::AddWhitelistedRange(subnet);
+ }
+ }
+
CService addrProxy;
bool fProxy = false;
if (mapArgs.count("-proxy")) {
@@ -807,13 +839,21 @@ bool AppInit2(boost::thread_group& threadGroup)
bool fBound = false;
if (fListen) {
- if (mapArgs.count("-bind")) {
+ if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
}
+ BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) {
+ CService addrBind;
+ if (!Lookup(strBind.c_str(), addrBind, 0, false))
+ return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
+ if (addrBind.GetPort() == 0)
+ return InitError(strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind));
+ fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST));
+ }
}
else {
struct in_addr inaddr_any;
@@ -1046,10 +1086,10 @@ bool AppInit2(boost::thread_group& threadGroup)
InitWarning(msg);
}
else if (nLoadWalletRet == DB_TOO_NEW)
- strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin") << "\n";
+ strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin Core") << "\n";
else if (nLoadWalletRet == DB_NEED_REWRITE)
{
- strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n";
+ strErrors << _("Wallet needed to be rewritten: restart Bitcoin Core to complete") << "\n";
LogPrintf("%s", strErrors.str());
return InitError(strErrors.str());
}
@@ -1191,7 +1231,6 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
#endif
- InitRespendFilter();
StartNode(threadGroup);
if (fServer)
StartRPCThreads();
diff --git a/src/key.cpp b/src/key.cpp
index 3c4fa77e72..a253f8666a 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,11 +1,11 @@
-// Copyright (c) 2009-2013 The Bitcoin developers
+// Copyright (c) 2009-2014 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 "key.h"
#include "crypto/sha2.h"
-#include <openssl/rand.h>
+#include "random.h"
#ifdef USE_SECP256K1
#include <secp256k1.h>
@@ -194,7 +194,7 @@ public:
if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
if(fSkipCheck)
return true;
-
+
// d2i_ECPrivateKey returns true if parsing succeeds.
// This doesn't necessarily mean the key is valid.
if (EC_KEY_check_key(pkey))
@@ -412,7 +412,7 @@ bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
void CKey::MakeNewKey(bool fCompressedIn) {
do {
- RAND_bytes(vch, sizeof(vch));
+ GetRandBytes(vch, sizeof(vch));
} while (!Check(vch));
fValid = true;
fCompressed = fCompressedIn;
@@ -745,5 +745,3 @@ bool ECC_InitSanityCheck() {
return true;
#endif
}
-
-
diff --git a/src/keystore.h b/src/keystore.h
index 72411a1387..6a3a0dc13e 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -8,21 +8,12 @@
#include "key.h"
#include "sync.h"
-#include "script.h" // for CNoDestination
#include <boost/signals2/signal.hpp>
#include <boost/variant.hpp>
class CScript;
-/** A txout script template with a specific destination. It is either:
- * * CNoDestination: no destination set
- * * CKeyID: TX_PUBKEYHASH destination
- * * CScriptID: TX_SCRIPTHASH destination
- * A CTxDestination is the internal data type encoded in a CBitcoinAddress
- */
-typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
-
/** A virtual base class for key stores */
class CKeyStore
{
diff --git a/src/m4/bitcoin_find_bdb48.m4 b/src/m4/bitcoin_find_bdb48.m4
index 72ec49b635..5223163fe5 100644
--- a/src/m4/bitcoin_find_bdb48.m4
+++ b/src/m4/bitcoin_find_bdb48.m4
@@ -44,7 +44,7 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[
AC_MSG_WARN([Found Berkeley DB other than 4.8; wallets opened by this build will not be portable!])
],[
- AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore)])
+ AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore or --disable-wallet to disable wallet functionality)])
])
else
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdb48path}],db_cxx)
@@ -60,7 +60,7 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
])
done
if test "x$BDB_LIBS" = "x"; then
- AC_MSG_ERROR(libdb_cxx missing)
+ AC_MSG_ERROR([libdb_cxx missing, Bitcoin Core requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
fi
AC_SUBST(BDB_LIBS)
])
diff --git a/src/m4/bitcoin_qt.m4 b/src/m4/bitcoin_qt.m4
index 244b03a5c2..4c1d40c394 100644
--- a/src/m4/bitcoin_qt.m4
+++ b/src/m4/bitcoin_qt.m4
@@ -62,6 +62,7 @@ AC_DEFUN([BITCOIN_QT_INIT],[
AC_ARG_WITH([qt-incdir],[AS_HELP_STRING([--with-qt-incdir=INC_DIR],[specify qt include path (overridden by pkgconfig)])], [qt_include_path=$withval], [])
AC_ARG_WITH([qt-libdir],[AS_HELP_STRING([--with-qt-libdir=LIB_DIR],[specify qt lib path (overridden by pkgconfig)])], [qt_lib_path=$withval], [])
AC_ARG_WITH([qt-plugindir],[AS_HELP_STRING([--with-qt-plugindir=PLUGIN_DIR],[specify qt plugin path (overridden by pkgconfig)])], [qt_plugin_path=$withval], [])
+ AC_ARG_WITH([qt-translationdir],[AS_HELP_STRING([--with-qt-translationdir=PLUGIN_DIR],[specify qt translation path (overridden by pkgconfig)])], [qt_translation_path=$withval], [])
AC_ARG_WITH([qt-bindir],[AS_HELP_STRING([--with-qt-bindir=BIN_DIR],[specify qt bin path])], [qt_bin_path=$withval], [])
AC_ARG_WITH([qtdbus],
@@ -69,6 +70,8 @@ AC_DEFUN([BITCOIN_QT_INIT],[
[enable DBus support (default is yes if qt is enabled and QtDBus is found)])],
[use_dbus=$withval],
[use_dbus=auto])
+
+ AC_SUBST(QT_TRANSLATION_DIR,$qt_translation_path)
])
dnl Find the appropriate version of Qt libraries and includes.
@@ -86,14 +89,69 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
fi
if test x$use_pkgconfig = xyes; then
- if test x$PKG_CONFIG == x; then
- AC_MSG_ERROR(pkg-config not found.)
- fi
BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG([$2])])
else
BITCOIN_QT_CHECK([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG])
fi
+ dnl This is ugly and complicated. Yuck. Works as follows:
+ dnl We can't discern whether Qt4 builds are static or not. For Qt5, we can
+ dnl check a header to find out. When Qt is built statically, some plugins must
+ dnl be linked into the final binary as well. These plugins have changed between
+ dnl Qt4 and Qt5. With Qt5, languages moved into core and the WindowsIntegration
+ dnl plugin was added. Since we can't tell if Qt4 is static or not, it is
+ dnl assumed for windows builds.
+ dnl _BITCOIN_QT_CHECK_STATIC_PLUGINS does a quick link-check and appends the
+ dnl results to QT_LIBS.
+ BITCOIN_QT_CHECK([
+ TEMP_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$QT_INCLUDES
+ if test x$bitcoin_qt_got_major_vers == x5; then
+ _BITCOIN_QT_IS_STATIC
+ if test x$bitcoin_cv_static_qt == xyes; then
+ AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
+ if test x$qt_plugin_path != x; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
+ if test x$bitcoin_qt_got_major_vers == x5; then
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms"
+ else
+ QT_LIBS="$QT_LIBS -L$qt_plugin_path/codecs"
+ fi
+ fi
+ if test x$use_pkgconfig = xyes; then
+ PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"])
+ fi
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets])
+ if test x$TARGET_OS == xwindows; then
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows])
+ AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows])
+ elif test x$TARGET_OS == xlinux; then
+ PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"])
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static])
+ AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
+ elif test x$TARGET_OS == xdarwin; then
+ if test x$use_pkgconfig = xyes; then
+ PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"])
+ fi
+ AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)])
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa])
+ AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa])
+ fi
+ fi
+ else
+ if test x$TARGET_OS == xwindows; then
+ AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
+ _BITCOIN_QT_CHECK_STATIC_PLUGINS([
+ Q_IMPORT_PLUGIN(qcncodecs)
+ Q_IMPORT_PLUGIN(qjpcodecs)
+ Q_IMPORT_PLUGIN(qtwcodecs)
+ Q_IMPORT_PLUGIN(qkrcodecs)
+ Q_IMPORT_PLUGIN(AccessibleFactory)],
+ [-lqcncodecs -lqjpcodecs -lqtwcodecs -lqkrcodecs -lqtaccessiblewidgets])
+ fi
+ fi
+ CPPFLAGS=$TEMP_CPPFLAGS
+ ])
BITCOIN_QT_PATH_PROGS([MOC], [moc-qt${bitcoin_qt_got_major_vers} moc${bitcoin_qt_got_major_vers} moc], $qt_bin_path)
BITCOIN_QT_PATH_PROGS([UIC], [uic-qt${bitcoin_qt_got_major_vers} uic${bitcoin_qt_got_major_vers} uic], $qt_bin_path)
BITCOIN_QT_PATH_PROGS([RCC], [rcc-qt${bitcoin_qt_got_major_vers} rcc${bitcoin_qt_got_major_vers} rcc], $qt_bin_path)
@@ -307,22 +365,16 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
if test x$qt_lib_path != x; then
LIBS="$LIBS -L$qt_lib_path"
fi
- if test x$qt_plugin_path != x; then
- LIBS="$LIBS -L$qt_plugin_path/accessible"
- if test x$bitcoin_qt_got_major_vers == x5; then
- LIBS="$LIBS -L$qt_plugin_path/platforms"
- else
- LIBS="$LIBS -L$qt_plugin_path/codecs"
- fi
- fi
if test x$TARGET_OS == xwindows; then
AC_CHECK_LIB([imm32], [main],, BITCOIN_QT_FAIL(libimm32 not found))
fi
])
- BITCOIN_QT_CHECK(AC_CHECK_LIB([z] ,[main],,BITCOIN_QT_FAIL(zlib not found)))
- BITCOIN_QT_CHECK(AC_CHECK_LIB([png] ,[main],,BITCOIN_QT_FAIL(png not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([z] ,[main],,AC_MSG_WARN([zlib not found. Assuming qt has it built-in])))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([png] ,[main],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in])))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([jpeg] ,[main],,AC_MSG_WARN([libjpeg not found. Assuming qt has it built-in])))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([pcre16] ,[main],,AC_MSG_WARN([libpcre16 not found. Assuming qt has it built-in])))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Core] ,[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXCore not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Gui] ,[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXGui not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Network],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXNetwork not found)))
@@ -332,37 +384,6 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
QT_LIBS="$LIBS"
LIBS="$TEMP_LIBS"
- dnl This is ugly and complicated. Yuck. Works as follows:
- dnl We can't discern whether Qt4 builds are static or not. For Qt5, we can
- dnl check a header to find out. When Qt is built statically, some plugins must
- dnl be linked into the final binary as well. These plugins have changed between
- dnl Qt4 and Qt5. With Qt5, languages moved into core and the WindowsIntegration
- dnl plugin was added. Since we can't tell if Qt4 is static or not, it is
- dnl assumed for all non-pkg-config builds.
- dnl _BITCOIN_QT_CHECK_STATIC_PLUGINS does a quick link-check and appends the
- dnl results to QT_LIBS.
- BITCOIN_QT_CHECK([
- if test x$bitcoin_qt_got_major_vers == x5; then
- _BITCOIN_QT_IS_STATIC
- if test x$bitcoin_cv_static_qt == xyes; then
- AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets])
- if test x$TARGET_OS == xwindows; then
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows])
- fi
- fi
- else
- AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static])
- _BITCOIN_QT_CHECK_STATIC_PLUGINS([
- Q_IMPORT_PLUGIN(qcncodecs)
- Q_IMPORT_PLUGIN(qjpcodecs)
- Q_IMPORT_PLUGIN(qtwcodecs)
- Q_IMPORT_PLUGIN(qkrcodecs)
- Q_IMPORT_PLUGIN(AccessibleFactory)],
- [-lqcncodecs -lqjpcodecs -lqtwcodecs -lqkrcodecs -lqtaccessiblewidgets])
- fi
- ])
-
BITCOIN_QT_CHECK([
LIBS=
if test x$qt_lib_path != x; then
diff --git a/src/main.cpp b/src/main.cpp
index 490b7f56fe..e135e93adb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -7,7 +7,6 @@
#include "addrman.h"
#include "alert.h"
-#include "bloom.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "checkqueue.h"
@@ -41,11 +40,13 @@ CCriticalSection cs_main;
map<uint256, CBlockIndex*> mapBlockIndex;
CChain chainActive;
int64_t nTimeBestReceived = 0;
+CWaitableCriticalSection csBestBlock;
+CConditionVariable cvBlockChange;
int nScriptCheckThreads = 0;
bool fImporting = false;
bool fReindex = false;
-bool fBenchmark = false;
bool fTxIndex = false;
+bool fIsBareMultisigStd = true;
unsigned int nCoinCacheSize = 5000;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
@@ -94,7 +95,9 @@ namespace {
};
CBlockIndex *pindexBestInvalid;
- // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
+
+ // The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least
+ // as good as our current tip. Entries may be failed, though.
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
CCriticalSection cs_LastBlockFile;
@@ -123,15 +126,6 @@ namespace {
} // anon namespace
-// Bloom filter to limit respend relays to one
-static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000;
-static CBloomFilter doubleSpendFilter;
-void InitRespendFilter() {
- seed_insecure_rand();
- doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE);
-}
-
-
//////////////////////////////////////////////////////////////////////////////
//
// dispatching functions
@@ -158,7 +152,6 @@ struct CMainSignals {
} // anon namespace
-
void RegisterWallet(CWalletInterface* pwalletIn) {
g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
@@ -210,7 +203,7 @@ struct CBlockReject {
struct CNodeState {
// Accumulated misbehaviour score for this peer.
int nMisbehavior;
- // Whether this peer should be disconnected and banned.
+ // Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan;
// String name of this peer (debugging/logging purposes).
std::string name;
@@ -451,7 +444,7 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
return Genesis();
}
-CBlockIndex *CChain::FindFork(CBlockIndex *pindex) const {
+const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
if (pindex->nHeight > Height())
pindex = pindex->GetAncestor(Height());
while (pindex && !Contains(pindex))
@@ -602,9 +595,13 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
reason = "scriptpubkey";
return false;
}
+
if (whichType == TX_NULL_DATA)
nDataOut++;
- else if (txout.IsDust(::minRelayTxFee)) {
+ else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
+ reason = "bare-multisig";
+ return false;
+ } else if (txout.IsDust(::minRelayTxFee)) {
reason = "dust";
return false;
}
@@ -874,60 +871,6 @@ int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
return nMinFee;
}
-// Exponentially limit the rate of nSize flow to nLimit. nLimit unit is thousands-per-minute.
-bool RateLimitExceeded(double& dCount, int64_t& nLastTime, int64_t nLimit, unsigned int nSize)
-{
- static CCriticalSection csLimiter;
- int64_t nNow = GetTime();
-
- LOCK(csLimiter);
-
- dCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
- nLastTime = nNow;
- if (dCount >= nLimit*10*1000)
- return true;
- dCount += nSize;
- return false;
-}
-
-static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter)
-{
- // Relaying double-spend attempts to our peers lets them detect when
- // somebody might be trying to cheat them. However, blindly relaying
- // every double-spend across the entire network gives attackers
- // a denial-of-service attack: just generate a stream of double-spends
- // re-spending the same (limited) set of outpoints owned by the attacker.
- // So, we use a bloom filter and only relay (at most) the first double
- // spend for each outpoint. False-positives ("we have already relayed")
- // are OK, because if the peer doesn't hear about the double-spend
- // from us they are very likely to hear about it from another peer, since
- // each peer uses a different, randomized bloom filter.
-
- if (fInBlock || filter.contains(outPoint)) return false;
-
- // Apply an independent rate limit to double-spend relays
- static double dRespendCount;
- static int64_t nLastRespendTime;
- static int64_t nRespendLimit = GetArg("-limitrespendrelay", 100);
- unsigned int nSize = ::GetSerializeSize(doubleSpend, SER_NETWORK, PROTOCOL_VERSION);
-
- if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize))
- {
- LogPrint("mempool", "Double-spend relay rejected by rate limiter\n");
- return false;
- }
-
- LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize);
-
- // Clear the filter on average every MAX_DOUBLE_SPEND_BLOOM
- // insertions
- if (insecure_rand()%MAX_DOUBLESPEND_BLOOM == 0)
- filter.clear();
-
- filter.insert(outPoint);
-
- return true;
-}
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs, bool fRejectInsaneFee)
@@ -957,18 +900,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false;
// Check for conflicts with in-memory transactions
- bool relayableRespend = false;
{
LOCK(pool.cs); // protect pool.mapNextTx
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
COutPoint outpoint = tx.vin[i].prevout;
- // Does tx conflict with a member of the pool, and is it not equivalent to that member?
- if (pool.mapNextTx.count(outpoint) && !tx.IsEquivalentTo(*pool.mapNextTx[outpoint].ptx))
+ if (pool.mapNextTx.count(outpoint))
{
- relayableRespend = RelayableRespend(outpoint, tx, false, doubleSpendFilter);
- if (!relayableRespend)
- return false;
+ // Disable replacement feature for now
+ return false;
}
}
}
@@ -1048,15 +988,23 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// be annoying or make others' transactions take longer to confirm.
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
{
+ static CCriticalSection csFreeLimiter;
static double dFreeCount;
- static int64_t nLastFreeTime;
- static int64_t nFreeLimit = GetArg("-limitfreerelay", 15);
+ static int64_t nLastTime;
+ int64_t nNow = GetTime();
+
+ LOCK(csFreeLimiter);
- if (RateLimitExceeded(dFreeCount, nLastFreeTime, nFreeLimit, nSize))
+ // Use an exponentially decaying ~10-minute window:
+ dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
+ nLastTime = nNow;
+ // -limitfreerelay unit is thousand-bytes-per-minute
+ // At default rate it would take over a month to fill 1GB
+ if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
REJECT_INSUFFICIENTFEE, "insufficient priority");
-
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
+ dFreeCount += nSize;
}
if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
@@ -1070,21 +1018,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
{
return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString());
}
-
- if (relayableRespend)
- {
- RelayTransaction(tx);
- }
- else
- {
- // Store transaction in memory
- pool.addUnchecked(hash, entry);
- }
+ // Store transaction in memory
+ pool.addUnchecked(hash, entry);
}
g_signals.SyncTransaction(tx, NULL);
- return !relayableRespend;
+ return true;
}
@@ -1434,7 +1374,8 @@ void Misbehaving(NodeId pnode, int howmuch)
return;
state->nMisbehavior += howmuch;
- if (state->nMisbehavior >= GetArg("-banscore", 100))
+ int banscore = GetArg("-banscore", 100);
+ if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore)
{
LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
state->fShouldBan = true;
@@ -1749,6 +1690,12 @@ void ThreadScriptCheck() {
scriptcheckqueue.Thread();
}
+static int64_t nTimeVerify = 0;
+static int64_t nTimeConnect = 0;
+static int64_t nTimeIndex = 0;
+static int64_t nTimeCallbacks = 0;
+static int64_t nTimeTotal = 0;
+
bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
{
AssertLockHeld(cs_main);
@@ -1804,7 +1751,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
- int64_t nStart = GetTimeMicros();
+ int64_t nTimeStart = GetTimeMicros();
int64_t nFees = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
@@ -1854,9 +1801,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
vPos.push_back(std::make_pair(tx.GetHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
- int64_t nTime = GetTimeMicros() - nStart;
- if (fBenchmark)
- LogPrintf("- 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));
+ int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
+ LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
if (block.vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
return state.DoS(100,
@@ -1866,9 +1812,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
if (!control.Wait())
return state.DoS(100, false);
- int64_t nTime2 = GetTimeMicros() - nStart;
- if (fBenchmark)
- LogPrintf("- Verify %u txins: %.2fms (%.3fms/txin)\n", nInputs - 1, 0.001 * nTime2, nInputs <= 1 ? 0 : 0.001 * nTime2 / (nInputs-1));
+ int64_t nTime2 = GetTimeMicros(); nTimeVerify += nTime2 - nTimeStart;
+ LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime2 - nTimeStart), nInputs <= 1 ? 0 : 0.001 * (nTime2 - nTimeStart) / (nInputs-1), nTimeVerify * 0.000001);
if (fJustCheck)
return true;
@@ -1909,6 +1854,9 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
ret = view.SetBestBlock(pindex->GetBlockHash());
assert(ret);
+ int64_t nTime3 = GetTimeMicros(); nTimeIndex += nTime3 - nTime2;
+ LogPrint("bench", " - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeIndex * 0.000001);
+
// Watch for transactions paying to me
BOOST_FOREACH(const CTransaction& tx, block.vtx)
g_signals.SyncTransaction(tx, &block);
@@ -1918,13 +1866,16 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
g_signals.UpdatedTransaction(hashPrevBestCoinBase);
hashPrevBestCoinBase = block.vtx[0].GetHash();
+ int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3;
+ LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001);
+
return true;
}
// Update the on-disk chain state.
bool static WriteChainState(CValidationState &state) {
static int64_t nLastWrite = 0;
- if (!IsInitialBlockDownload() || pcoinsTip->GetCacheSize() > nCoinCacheSize || GetTimeMicros() > nLastWrite + 600*1000000) {
+ if (pcoinsTip->GetCacheSize() > nCoinCacheSize || (!IsInitialBlockDownload() && GetTimeMicros() > nLastWrite + 600*1000000)) {
// Typical CCoins structures on disk are around 100 bytes in size.
// Pushing a new one to the database can cause it to be written
// twice (once in the log, and once in the tables). This is already
@@ -1953,11 +1904,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
// New best block
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
+
LogPrintf("UpdateTip: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainActive.Tip()));
+ cvBlockChange.notify_all();
+
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
{
@@ -1994,8 +1948,7 @@ bool static DisconnectTip(CValidationState &state) {
return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
assert(view.Flush());
}
- if (fBenchmark)
- LogPrintf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
+ LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Write the chain state to disk, if necessary.
if (!WriteChainState(state))
return false;
@@ -2019,16 +1972,25 @@ bool static DisconnectTip(CValidationState &state) {
return true;
}
+static int64_t nTimeReadFromDisk = 0;
+static int64_t nTimeConnectTotal = 0;
+static int64_t nTimeFlush = 0;
+static int64_t nTimeChainState = 0;
+static int64_t nTimePostConnect = 0;
+
// Connect a new block to chainActive.
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
// Read block from disk.
+ int64_t nTime1 = GetTimeMicros();
CBlock block;
if (!ReadBlockFromDisk(block, pindexNew))
return state.Abort(_("Failed to read block"));
// Apply the block atomically to the chain state.
- int64_t nStart = GetTimeMicros();
+ int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
+ int64_t nTime3;
+ LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{
CCoinsViewCache view(*pcoinsTip, true);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
@@ -2038,13 +2000,17 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
return error("ConnectTip() : ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
}
mapBlockSource.erase(inv.hash);
+ nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
+ LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
assert(view.Flush());
}
- if (fBenchmark)
- LogPrintf("- Connect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
+ int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
+ LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
// Write the chain state to disk, if necessary.
if (!WriteChainState(state))
return false;
+ int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
+ LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
// Remove conflicting transactions from the mempool.
list<CTransaction> txConflicted;
mempool.removeForBlock(block.vtx, pindexNew->nHeight, txConflicted);
@@ -2060,6 +2026,9 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
SyncWithWallets(tx, &block);
}
+ int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
+ LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
+ LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
return true;
}
@@ -2082,7 +2051,7 @@ static CBlockIndex* FindMostWorkChain() {
CBlockIndex *pindexTest = pindexNew;
bool fInvalidAncestor = false;
while (pindexTest && !chainActive.Contains(pindexTest)) {
- if (!pindexTest->IsValid(BLOCK_VALID_TRANSACTIONS) || !(pindexTest->nStatus & BLOCK_HAVE_DATA)) {
+ if (pindexTest->nStatus & BLOCK_FAILED_MASK) {
// Candidate has an invalid ancestor, remove entire chain from the set.
if (pindexBestInvalid == NULL || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
pindexBestInvalid = pindexNew;
@@ -2092,6 +2061,7 @@ static CBlockIndex* FindMostWorkChain() {
setBlockIndexValid.erase(pindexFailed);
pindexFailed = pindexFailed->pprev;
}
+ setBlockIndexValid.erase(pindexTest);
fInvalidAncestor = true;
break;
}
@@ -2106,8 +2076,8 @@ static CBlockIndex* FindMostWorkChain() {
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) {
AssertLockHeld(cs_main);
bool fInvalidFound = false;
- CBlockIndex *pindexOldTip = chainActive.Tip();
- CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
+ const CBlockIndex *pindexOldTip = chainActive.Tip();
+ const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
// Disconnect active blocks which are no longer in the best chain.
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
@@ -2138,6 +2108,15 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
return false;
}
} else {
+ // Delete all entries in setBlockIndexValid that are worse than our new current block.
+ // Note that we can't delete the current block itself, as we may need to return to it later in case a
+ // reorganization to a better block fails.
+ std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexValid.begin();
+ while (setBlockIndexValid.value_comp()(*it, chainActive.Tip())) {
+ setBlockIndexValid.erase(it++);
+ }
+ // Either the current tip or a successor of it we're working towards is left in setBlockIndexValid.
+ assert(!setBlockIndexValid.empty());
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock.
break;
@@ -2520,7 +2499,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
return false;
if (!CheckBlock(block, state)) {
- if (state.Invalid() && !state.CorruptionPossible()) {
+ if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
}
return false;
@@ -3082,7 +3061,7 @@ bool CVerifyDB::VerifyDB(int nCheckLevel, int nCheckDepth)
}
}
// 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) {
+ if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= nCoinCacheSize) {
bool fClean = true;
if (!DisconnectBlock(block, state, pindex, coins, &fClean))
return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
@@ -3658,7 +3637,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->fSuccessfullyConnected = true;
- LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d\n", pfrom->cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), pfrom->id);
+ string remoteAddr;
+ if (fLogIPs)
+ remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
+
+ LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
+ pfrom->cleanSubVer, pfrom->nVersion,
+ pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
+ remoteAddr);
AddTimeData(pfrom->addr, nTime);
}
@@ -3956,6 +3942,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS);
if (nEvicted > 0)
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
+ } else if (pfrom->fWhitelisted) {
+ // Always relay transactions received from whitelisted peers, even
+ // if they are already in the mempool (allowing the node to function
+ // as a gateway for nodes hidden behind it).
+ RelayTransaction(tx);
}
int nDoS = 0;
if (state.IsInvalid(nDoS))
@@ -4379,7 +4370,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (pingSend) {
uint64_t nonce = 0;
while (nonce == 0) {
- RAND_bytes((unsigned char*)&nonce, sizeof(nonce));
+ GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
}
pto->fPingQueued = false;
pto->nPingUsecStart = GetTimeMicros();
@@ -4449,11 +4440,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
CNodeState &state = *State(pto->GetId());
if (state.fShouldBan) {
- if (pto->addr.IsLocal())
- LogPrintf("Warning: not banning local node %s!\n", pto->addr.ToString());
+ if (pto->fWhitelisted)
+ LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
else {
pto->fDisconnect = true;
- CNode::Ban(pto->addr);
+ if (pto->addr.IsLocal())
+ LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
+ else
+ CNode::Ban(pto->addr);
}
state.fShouldBan = false;
}
diff --git a/src/main.h b/src/main.h
index 547e7305ea..01d3f119e1 100644
--- a/src/main.h
+++ b/src/main.h
@@ -89,11 +89,13 @@ extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern const std::string strMessageMagic;
extern int64_t nTimeBestReceived;
+extern CWaitableCriticalSection csBestBlock;
+extern CConditionVariable cvBlockChange;
extern bool fImporting;
extern bool fReindex;
-extern bool fBenchmark;
extern int nScriptCheckThreads;
extern bool fTxIndex;
+extern bool fIsBareMultisigStd;
extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee;
@@ -111,9 +113,6 @@ struct CNodeStateStats;
struct CBlockTemplate;
-/** Initialize respend bloom filter **/
-void InitRespendFilter();
-
/** Register a wallet to receive updates from core */
void RegisterWallet(CWalletInterface* pwalletIn);
/** Unregister a wallet from core */
@@ -1071,7 +1070,7 @@ public:
CBlockIndex *FindFork(const CBlockLocator &locator) const;
/** Find the last common block between this chain and a block index entry. */
- CBlockIndex *FindFork(CBlockIndex *pindex) const;
+ const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
};
/** The currently-connected chain of blocks. */
diff --git a/src/miner.cpp b/src/miner.cpp
index ec56c71192..9408d2c5aa 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -402,17 +402,8 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
return CreateNewBlock(scriptPubKey);
}
-bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
+bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
- uint256 hash = pblock->GetHash();
- uint256 hashTarget = uint256().SetCompact(pblock->nBits);
-
- if (hash > hashTarget)
- return false;
-
- //// debug print
- LogPrintf("BitcoinMiner:\n");
- LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
pblock->print();
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@@ -500,7 +491,9 @@ void static BitcoinMiner(CWallet *pwallet)
assert(hash == pblock->GetHash());
SetThreadPriority(THREAD_PRIORITY_NORMAL);
- CheckWork(pblock, *pwallet, reservekey);
+ LogPrintf("BitcoinMiner:\n");
+ LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
+ ProcessBlockFound(pblock, *pwallet, reservekey);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// In regression test mode, stop mining after a block is found.
diff --git a/src/net.cpp b/src/net.cpp
index 6a660dc9bd..62124514c8 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -50,7 +50,16 @@
using namespace std;
using namespace boost;
-static const int MAX_OUTBOUND_CONNECTIONS = 8;
+namespace {
+ const int MAX_OUTBOUND_CONNECTIONS = 8;
+
+ struct ListenSocket {
+ SOCKET socket;
+ bool whitelisted;
+
+ ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {}
+ };
+}
//
// Global state variables
@@ -65,7 +74,7 @@ static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
static CNode* pnodeSync = NULL;
uint64_t nLocalHostNonce = 0;
-static std::vector<SOCKET> vhListenSocket;
+static std::vector<ListenSocket> vhListenSocket;
CAddrMan addrman;
int nMaxConnections = 125;
@@ -323,7 +332,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
{
if (!RecvLine(hSocket, strLine))
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
if (pszKeyword == NULL)
@@ -334,7 +343,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
break;
}
}
- closesocket(hSocket);
+ CloseSocket(hSocket);
if (strLine.find("<") != string::npos)
strLine = strLine.substr(0, strLine.find("<"));
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
@@ -348,7 +357,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
return true;
}
}
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("GetMyExternalIP() : connection closed");
}
@@ -447,7 +456,7 @@ CNode* FindNode(const CNetAddr& ip)
return NULL;
}
-CNode* FindNode(std::string addrName)
+CNode* FindNode(const std::string& addrName)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -492,14 +501,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
addrman.Attempt(addrConnect);
// Set to non-blocking
-#ifdef WIN32
- u_long nOne = 1;
- if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
- LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError()));
-#else
- if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
- LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno));
-#endif
+ if (!SetSocketNonBlocking(hSocket, true))
+ LogPrintf("ConnectNode: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
// Add node
CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
@@ -524,8 +527,7 @@ void CNode::CloseSocketDisconnect()
if (hSocket != INVALID_SOCKET)
{
LogPrint("net", "disconnecting peer=%d\n", id);
- closesocket(hSocket);
- hSocket = INVALID_SOCKET;
+ CloseSocket(hSocket);
}
// in case this fails, we'll empty the recv buffer when the CNode is deleted
@@ -546,7 +548,7 @@ void CNode::PushVersion()
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
CAddress addrMe = GetLocalAddress(&addr);
- RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
+ GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
if (fLogIPs)
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
else
@@ -593,6 +595,24 @@ bool CNode::Ban(const CNetAddr &addr) {
return true;
}
+
+std::vector<CSubNet> CNode::vWhitelistedRange;
+CCriticalSection CNode::cs_vWhitelistedRange;
+
+bool CNode::IsWhitelistedRange(const CNetAddr &addr) {
+ LOCK(cs_vWhitelistedRange);
+ BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) {
+ if (subnet.Match(addr))
+ return true;
+ }
+ return false;
+}
+
+void CNode::AddWhitelistedRange(const CSubNet &subnet) {
+ LOCK(cs_vWhitelistedRange);
+ vWhitelistedRange.push_back(subnet);
+}
+
#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats)
@@ -609,6 +629,7 @@ void CNode::copyStats(CNodeStats &stats)
X(nStartingHeight);
X(nSendBytes);
X(nRecvBytes);
+ X(fWhitelisted);
stats.fSyncNode = (this == pnodeSync);
// It is common for nodes with good ping times to suddenly become lagged,
@@ -848,9 +869,9 @@ void ThreadSocketHandler()
SOCKET hSocketMax = 0;
bool have_fds = false;
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
- FD_SET(hListenSocket, &fdsetRecv);
- hSocketMax = max(hSocketMax, hListenSocket);
+ BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
+ FD_SET(hListenSocket.socket, &fdsetRecv);
+ hSocketMax = max(hSocketMax, hListenSocket.socket);
have_fds = true;
}
@@ -917,13 +938,13 @@ void ThreadSocketHandler()
//
// Accept new connections
//
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
+ BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket)
{
- if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
+ if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv))
{
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
- SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
+ SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
CAddress addr;
int nInbound = 0;
@@ -931,6 +952,7 @@ void ThreadSocketHandler()
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
LogPrintf("Warning: Unknown socket family\n");
+ bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -946,17 +968,18 @@ void ThreadSocketHandler()
}
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
}
- else if (CNode::IsBanned(addr))
+ else if (CNode::IsBanned(addr) && !whitelisted)
{
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
- closesocket(hSocket);
+ CloseSocket(hSocket);
}
else
{
CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
+ pnode->fWhitelisted = whitelisted;
{
LOCK(cs_vNodes);
@@ -1198,6 +1221,18 @@ void MapPort(bool)
void ThreadDNSAddressSeed()
{
+ // goal: only query DNS seeds if address need is acute
+ if ((addrman.size() > 0) &&
+ (!GetBoolArg("-forcednsseed", false))) {
+ MilliSleep(11 * 1000);
+
+ LOCK(cs_vNodes);
+ if (vNodes.size() >= 2) {
+ LogPrintf("P2P peers available. Skipped DNS seeding.\n");
+ return;
+ }
+ }
+
const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
int found = 0;
@@ -1449,7 +1484,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
if (!pszDest) {
if (IsLocal(addrConnect) ||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
- FindNode(addrConnect.ToStringIPPort().c_str()))
+ FindNode(addrConnect.ToStringIPPort()))
return false;
} else if (FindNode(pszDest))
return false;
@@ -1580,7 +1615,7 @@ void ThreadMessageHandler()
-bool BindListenPort(const CService &addrBind, string& strError)
+bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
{
strError = "";
int nOne = 1;
@@ -1613,14 +1648,9 @@ bool BindListenPort(const CService &addrBind, string& strError)
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif
-#ifdef WIN32
// Set to non-blocking, incoming connections will also inherit this
- if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
-#else
- if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
-#endif
- {
- strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()));
+ if (!SetSocketNonBlocking(hListenSocket, true)) {
+ strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
return false;
}
@@ -1649,6 +1679,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
LogPrintf("%s\n", strError);
+ CloseSocket(hListenSocket);
return false;
}
LogPrintf("Bound to %s\n", addrBind.ToString());
@@ -1658,12 +1689,13 @@ bool BindListenPort(const CService &addrBind, string& strError)
{
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
+ CloseSocket(hListenSocket);
return false;
}
- vhListenSocket.push_back(hListenSocket);
+ vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted));
- if (addrBind.IsRoutable() && fDiscover)
+ if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
AddLocal(addrBind, LOCAL_BIND);
return true;
@@ -1787,11 +1819,11 @@ public:
// Close sockets
BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->hSocket != INVALID_SOCKET)
- closesocket(pnode->hSocket);
- BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
- if (hListenSocket != INVALID_SOCKET)
- if (closesocket(hListenSocket) == SOCKET_ERROR)
- LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
+ CloseSocket(pnode->hSocket);
+ BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket)
+ if (hListenSocket.socket != INVALID_SOCKET)
+ if (!CloseSocket(hListenSocket.socket))
+ LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
// clean up some globals (to help leak detection)
BOOST_FOREACH(CNode *pnode, vNodes)
@@ -1931,7 +1963,7 @@ bool CAddrDB::Write(const CAddrMan& addr)
{
// Generate random temporary filename
unsigned short randv = 0;
- RAND_bytes((unsigned char *)&randv, sizeof(randv));
+ GetRandBytes((unsigned char*)&randv, sizeof(randv));
std::string tmpfn = strprintf("peers.dat.%04x", randv);
// serialize addresses, checksum data up to that point, then append csum
diff --git a/src/net.h b/src/net.h
index c2a0416455..a8795a4760 100644
--- a/src/net.h
+++ b/src/net.h
@@ -13,6 +13,7 @@
#include "mruset.h"
#include "netbase.h"
#include "protocol.h"
+#include "random.h"
#include "sync.h"
#include "uint256.h"
#include "util.h"
@@ -26,7 +27,6 @@
#include <boost/foreach.hpp>
#include <boost/signals2/signal.hpp>
-#include <openssl/rand.h>
class CAddrMan;
class CBlockIndex;
@@ -59,12 +59,13 @@ bool RecvLine(SOCKET hSocket, std::string& strLine);
bool GetMyExternalIP(CNetAddr& ipRet);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
+CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
void MapPort(bool fUseUPnP);
unsigned short GetListenPort();
-bool BindListenPort(const CService &bindAddr, std::string& strError);
+bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
void StartNode(boost::thread_group& threadGroup);
bool StopNode();
void SocketSendData(CNode *pnode);
@@ -154,6 +155,7 @@ public:
uint64_t nSendBytes;
uint64_t nRecvBytes;
bool fSyncNode;
+ bool fWhitelisted;
double dPingTime;
double dPingWait;
std::string addrLocal;
@@ -236,6 +238,7 @@ public:
// store the sanitized version in cleanSubVer. The original should be used when dealing with
// the network or wire types and the cleaned string used when displayed or logged.
std::string strSubVer, cleanSubVer;
+ bool fWhitelisted; // This peer can bypass DoS banning.
bool fOneShot;
bool fClient;
bool fInbound;
@@ -259,6 +262,11 @@ protected:
static std::map<CNetAddr, int64_t> setBanned;
static CCriticalSection cs_setBanned;
+ // Whitelisted ranges. Any node connecting from these is automatically
+ // whitelisted (as well as those connecting to whitelisted binds).
+ static std::vector<CSubNet> vWhitelistedRange;
+ static CCriticalSection cs_vWhitelistedRange;
+
// Basic fuzz-testing
void Fuzz(int nChance); // modifies ssSend
@@ -305,6 +313,7 @@ public:
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
nVersion = 0;
strSubVer = "";
+ fWhitelisted = false;
fOneShot = false;
fClient = false; // set by version message
fInbound = fInboundIn;
@@ -347,13 +356,11 @@ public:
~CNode()
{
- if (hSocket != INVALID_SOCKET)
- {
- closesocket(hSocket);
- hSocket = INVALID_SOCKET;
- }
+ CloseSocket(hSocket);
+
if (pfilter)
delete pfilter;
+
GetNodeSignals().FinalizeNode(GetId());
}
@@ -720,6 +727,9 @@ public:
static bool Ban(const CNetAddr &ip);
void copyStats(CNodeStats &stats);
+ static bool IsWhitelistedRange(const CNetAddr &ip);
+ static void AddWhitelistedRange(const CSubNet &subnet);
+
// Network stats
static void RecordBytesRecv(uint64_t bytes);
static void RecordBytesSent(uint64_t bytes);
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 067cfa024b..1031e7e38a 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -7,10 +7,6 @@
#include "bitcoin-config.h"
#endif
-#ifdef HAVE_GETADDRINFO_A
-#include <netdb.h>
-#endif
-
#include "netbase.h"
#include "hash.h"
@@ -18,6 +14,10 @@
#include "uint256.h"
#include "util.h"
+#ifdef HAVE_GETADDRINFO_A
+#include <netdb.h>
+#endif
+
#ifndef WIN32
#if HAVE_INET_PTON
#include <arpa/inet.h>
@@ -218,7 +218,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
LogPrintf("SOCKS5 connecting %s\n", strDest);
if (strDest.size() > 255)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Hostname too long");
}
char pszSocks5Init[] = "\5\1\0";
@@ -227,18 +227,18 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
ssize_t ret = send(hSocket, pszSocks5Init, nSize, MSG_NOSIGNAL);
if (ret != nSize)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error sending to proxy");
}
char pchRet1[2];
if (recv(hSocket, pchRet1, 2, 0) != 2)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading proxy response");
}
if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Proxy failed to initialize");
}
string strSocks5("\5\1");
@@ -250,23 +250,23 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
if (ret != (ssize_t)strSocks5.size())
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error sending to proxy");
}
char pchRet2[4];
if (recv(hSocket, pchRet2, 4, 0) != 4)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading proxy response");
}
if (pchRet2[0] != 0x05)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Proxy failed to accept request");
}
if (pchRet2[1] != 0x00)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
switch (pchRet2[1])
{
case 0x01: return error("Proxy error: general failure");
@@ -282,7 +282,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
}
if (pchRet2[2] != 0x00)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error: malformed proxy response");
}
char pchRet3[256];
@@ -294,23 +294,23 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
{
ret = recv(hSocket, pchRet3, 1, 0) != 1;
if (ret) {
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading from proxy");
}
int nRecv = pchRet3[0];
ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
break;
}
- default: closesocket(hSocket); return error("Error: malformed proxy response");
+ default: CloseSocket(hSocket); return error("Error: malformed proxy response");
}
if (ret)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading from proxy");
}
if (recv(hSocket, pchRet3, 2, 0) != 2)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading from proxy");
}
LogPrintf("SOCKS5 connected %s\n", strDest);
@@ -331,22 +331,16 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (hSocket == INVALID_SOCKET)
return false;
+
#ifdef SO_NOSIGPIPE
int set = 1;
+ // Different way of disabling SIGPIPE on BSD
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif
-#ifdef WIN32
- u_long fNonblock = 1;
- if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
-#else
- int fFlags = fcntl(hSocket, F_GETFL, 0);
- if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
-#endif
- {
- closesocket(hSocket);
- return false;
- }
+ // Set to non-blocking
+ if (!SetSocketNonBlocking(hSocket, true))
+ return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
{
@@ -365,13 +359,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
if (nRet == 0)
{
LogPrint("net", "connection to %s timeout\n", addrConnect.ToString());
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
if (nRet == SOCKET_ERROR)
{
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
socklen_t nRetSize = sizeof(nRet);
@@ -382,13 +376,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
#endif
{
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
if (nRet != 0)
{
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
}
@@ -399,25 +393,15 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
#endif
{
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
}
- // this isn't even strictly necessary
- // CNode::ConnectNode immediately turns the socket back to non-blocking
- // but we'll turn it back to blocking just in case
-#ifdef WIN32
- fNonblock = 0;
- if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
-#else
- fFlags = fcntl(hSocket, F_GETFL, 0);
- if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR)
-#endif
- {
- closesocket(hSocket);
- return false;
- }
+ // This is required when using SOCKS5 proxy!
+ // CNode::ConnectNode turns the socket back to non-blocking.
+ if (!SetSocketNonBlocking(hSocket, false))
+ return error("ConnectSocketDirectly: Setting socket to blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
hSocketRet = hSocket;
return true;
@@ -1258,3 +1242,45 @@ std::string NetworkErrorString(int err)
return strprintf("%s (%d)", s, err);
}
#endif
+
+bool CloseSocket(SOCKET& hSocket)
+{
+ if (hSocket == INVALID_SOCKET)
+ return false;
+#ifdef WIN32
+ int ret = closesocket(hSocket);
+#else
+ int ret = close(hSocket);
+#endif
+ hSocket = INVALID_SOCKET;
+ return ret != SOCKET_ERROR;
+}
+
+bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking)
+{
+ if (fNonBlocking) {
+#ifdef WIN32
+ u_long nOne = 1;
+ if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
+#else
+ int fFlags = fcntl(hSocket, F_GETFL, 0);
+ if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
+#endif
+ CloseSocket(hSocket);
+ return false;
+ }
+ } else {
+#ifdef WIN32
+ u_long nZero = 0;
+ if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
+#else
+ int fFlags = fcntl(hSocket, F_GETFL, 0);
+ if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
+#endif
+ CloseSocket(hSocket);
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/netbase.h b/src/netbase.h
index ad1e230834..7d83e35344 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -178,5 +178,9 @@ bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nCon
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
/** Return readable error string for a network error code */
std::string NetworkErrorString(int err);
+/** Close socket and set hSocket to INVALID_SOCKET */
+bool CloseSocket(SOCKET& hSocket);
+/** Disable or enable blocking-mode for a socket */
+bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);
#endif
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 5df8f19729..f336d47e83 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -282,7 +282,7 @@ void AddressBookPage::on_exportButton_clicked()
if(!writer.write()) {
QMessageBox::critical(this, tr("Exporting Failed"),
- tr("There was an error trying to save the address list to %1.").arg(filename));
+ tr("There was an error trying to save the address list to %1. Please try again.").arg(filename));
}
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 7c4af25edf..a43e7cb756 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -34,6 +34,7 @@
#include <boost/filesystem/operations.hpp>
#include <QApplication>
+#include <QDebug>
#include <QLibraryInfo>
#include <QLocale>
#include <QMessageBox>
@@ -52,7 +53,13 @@ Q_IMPORT_PLUGIN(qkrcodecs)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#else
Q_IMPORT_PLUGIN(AccessibleFactory)
+#if defined(QT_QPA_PLATFORM_XCB)
+Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
+#elif defined(QT_QPA_PLATFORM_WINDOWS)
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
+#elif defined(QT_QPA_PLATFORM_COCOA)
+Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
+#endif
#endif
#endif
@@ -237,7 +244,7 @@ void BitcoinCore::initialize()
{
try
{
- LogPrintf("Running AppInit2 in thread\n");
+ qDebug() << __func__ << ": Running AppInit2 in thread";
int rv = AppInit2(threadGroup);
if(rv)
{
@@ -258,11 +265,11 @@ void BitcoinCore::shutdown()
{
try
{
- LogPrintf("Running Shutdown in thread\n");
+ qDebug() << __func__ << ": Running Shutdown in thread";
threadGroup.interrupt_all();
threadGroup.join_all();
Shutdown();
- LogPrintf("Shutdown finished\n");
+ qDebug() << __func__ << ": Shutdown finished";
emit shutdownResult(1);
} catch (std::exception& e) {
handleRunawayException(&e);
@@ -285,15 +292,17 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv):
returnValue(0)
{
setQuitOnLastWindowClosed(false);
- startThread();
}
BitcoinApplication::~BitcoinApplication()
{
- LogPrintf("Stopping thread\n");
- emit stopThread();
- coreThread->wait();
- LogPrintf("Stopped thread\n");
+ if(coreThread)
+ {
+ qDebug() << __func__ << ": Stopping thread";
+ emit stopThread();
+ coreThread->wait();
+ qDebug() << __func__ << ": Stopped thread";
+ }
delete window;
window = 0;
@@ -336,6 +345,8 @@ void BitcoinApplication::createSplashScreen(bool isaTestNet)
void BitcoinApplication::startThread()
{
+ if(coreThread)
+ return;
coreThread = new QThread(this);
BitcoinCore *executor = new BitcoinCore();
executor->moveToThread(coreThread);
@@ -355,13 +366,15 @@ void BitcoinApplication::startThread()
void BitcoinApplication::requestInitialize()
{
- LogPrintf("Requesting initialize\n");
+ qDebug() << __func__ << ": Requesting initialize";
+ startThread();
emit requestedInitialize();
}
void BitcoinApplication::requestShutdown()
{
- LogPrintf("Requesting shutdown\n");
+ qDebug() << __func__ << ": Requesting shutdown";
+ startThread();
window->hide();
window->setClientModel(0);
pollShutdownTimer->stop();
@@ -383,7 +396,7 @@ void BitcoinApplication::requestShutdown()
void BitcoinApplication::initializeResult(int retval)
{
- LogPrintf("Initialization result: %i\n", retval);
+ qDebug() << __func__ << ": Initialization result: " << retval;
// Set exit result: 0 if successful, 1 if failure
returnValue = retval ? 0 : 1;
if(retval)
@@ -393,8 +406,6 @@ void BitcoinApplication::initializeResult(int retval)
paymentServer->setOptionsModel(optionsModel);
#endif
- emit splashFinished(window);
-
clientModel = new ClientModel(optionsModel);
window->setClientModel(clientModel);
@@ -411,6 +422,8 @@ void BitcoinApplication::initializeResult(int retval)
}
#endif
+ emit splashFinished(window);
+
// If -min option passed, start window minimized.
if(GetBoolArg("-min", false))
{
@@ -438,7 +451,7 @@ void BitcoinApplication::initializeResult(int retval)
void BitcoinApplication::shutdownResult(int retval)
{
- LogPrintf("Shutdown result: %i\n", retval);
+ qDebug() << __func__ << ": Shutdown result: " << retval;
quit(); // Exit main loop after shutdown finished
}
@@ -476,6 +489,9 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
+
+ GUIUtil::SubstituteFonts();
+
BitcoinApplication app(argc, argv);
#if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
@@ -518,14 +534,14 @@ int main(int argc, char *argv[])
/// - Do not call GetDataDir(true) before this step finishes
if (!boost::filesystem::is_directory(GetDataDir(false)))
{
- QMessageBox::critical(0, QObject::tr("Bitcoin"),
+ QMessageBox::critical(0, QObject::tr("Bitcoin Core"),
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
return 1;
}
try {
ReadConfigFile(mapArgs, mapMultiArgs);
} catch(std::exception &e) {
- QMessageBox::critical(0, QObject::tr("Bitcoin"),
+ QMessageBox::critical(0, QObject::tr("Bitcoin Core"),
QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
return false;
}
@@ -538,7 +554,7 @@ int main(int argc, char *argv[])
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
if (!SelectParamsFromCommandLine()) {
- QMessageBox::critical(0, QObject::tr("Bitcoin"), QObject::tr("Error: Invalid combination of -regtest and -testnet."));
+ QMessageBox::critical(0, QObject::tr("Bitcoin Core"), QObject::tr("Error: Invalid combination of -regtest and -testnet."));
return 1;
}
#ifdef ENABLE_WALLET
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index 357c6470d3..6dba62035b 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -4,7 +4,6 @@
<file alias="address-book">res/icons/address-book.png</file>
<file alias="quit">res/icons/quit.png</file>
<file alias="send">res/icons/send.png</file>
- <file alias="toolbar">res/icons/toolbar.png</file>
<file alias="connect_0">res/icons/connect0_16.png</file>
<file alias="connect_1">res/icons/connect1_16.png</file>
<file alias="connect_2">res/icons/connect2_16.png</file>
@@ -24,7 +23,6 @@
<file alias="editcopy">res/icons/editcopy.png</file>
<file alias="add">res/icons/add.png</file>
<file alias="bitcoin_testnet">res/icons/bitcoin_testnet.png</file>
- <file alias="toolbar_testnet">res/icons/toolbar_testnet.png</file>
<file alias="edit">res/icons/edit.png</file>
<file alias="history">res/icons/history.png</file>
<file alias="overview">res/icons/overview.png</file>
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 25ad0c66af..6466039013 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -9,19 +9,186 @@
#include "qvaluecombobox.h"
#include <QApplication>
-#include <QDoubleSpinBox>
+#include <QAbstractSpinBox>
#include <QHBoxLayout>
#include <QKeyEvent>
-#include <qmath.h> // for qPow()
+#include <QLineEdit>
+
+/** QSpinBox that uses fixed-point numbers internally and uses our own
+ * formatting/parsing functions.
+ */
+class AmountSpinBox: public QAbstractSpinBox
+{
+ Q_OBJECT
+public:
+ explicit AmountSpinBox(QWidget *parent):
+ QAbstractSpinBox(parent),
+ currentUnit(BitcoinUnits::BTC),
+ singleStep(100000) // satoshis
+ {
+ setAlignment(Qt::AlignRight);
+
+ connect(lineEdit(), SIGNAL(textEdited(QString)), this, SIGNAL(valueChanged()));
+ }
+
+ QValidator::State validate(QString &text, int &pos) const
+ {
+ if(text.isEmpty())
+ return QValidator::Intermediate;
+ bool valid = false;
+ parse(text, &valid);
+ /* Make sure we return Intermediate so that fixup() is called on defocus */
+ return valid ? QValidator::Intermediate : QValidator::Invalid;
+ }
+
+ void fixup(QString &input) const
+ {
+ bool valid = false;
+ qint64 val = parse(input, &valid);
+ if(valid)
+ {
+ input = BitcoinUnits::format(currentUnit, val, false, BitcoinUnits::separatorAlways);
+ lineEdit()->setText(input);
+ }
+ }
+
+ qint64 value(bool *valid_out=0) const
+ {
+ return parse(text(), valid_out);
+ }
+
+ void setValue(qint64 value)
+ {
+ lineEdit()->setText(BitcoinUnits::format(currentUnit, value, false, BitcoinUnits::separatorAlways));
+ emit valueChanged();
+ }
+
+ void stepBy(int steps)
+ {
+ bool valid = false;
+ qint64 val = value(&valid);
+ val = val + steps * singleStep;
+ val = qMin(qMax(val, Q_INT64_C(0)), BitcoinUnits::maxMoney());
+ setValue(val);
+ }
+
+ StepEnabled stepEnabled() const
+ {
+ StepEnabled rv = 0;
+ if(text().isEmpty()) // Allow step-up with empty field
+ return StepUpEnabled;
+ bool valid = false;
+ qint64 val = value(&valid);
+ if(valid)
+ {
+ if(val > 0)
+ rv |= StepDownEnabled;
+ if(val < BitcoinUnits::maxMoney())
+ rv |= StepUpEnabled;
+ }
+ return rv;
+ }
+
+ void setDisplayUnit(int unit)
+ {
+ bool valid = false;
+ qint64 val = value(&valid);
+
+ currentUnit = unit;
+
+ if(valid)
+ setValue(val);
+ else
+ clear();
+ }
+
+ void setSingleStep(qint64 step)
+ {
+ singleStep = step;
+ }
+
+ QSize minimumSizeHint() const
+ {
+ if(cachedMinimumSizeHint.isEmpty())
+ {
+ ensurePolished();
+
+ const QFontMetrics fm(fontMetrics());
+ int h = lineEdit()->minimumSizeHint().height();
+ int w = fm.width(BitcoinUnits::format(BitcoinUnits::BTC, BitcoinUnits::maxMoney(), false, BitcoinUnits::separatorAlways));
+ w += 2; // cursor blinking space
+
+ QStyleOptionSpinBox opt;
+ initStyleOption(&opt);
+ QSize hint(w, h);
+ QSize extra(35, 6);
+ opt.rect.setSize(hint + extra);
+ extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
+ QStyle::SC_SpinBoxEditField, this).size();
+ // get closer to final result by repeating the calculation
+ opt.rect.setSize(hint + extra);
+ extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
+ QStyle::SC_SpinBoxEditField, this).size();
+ hint += extra;
+
+ opt.rect = rect();
+
+ cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
+ .expandedTo(QApplication::globalStrut());
+ }
+ return cachedMinimumSizeHint;
+ }
+private:
+ int currentUnit;
+ qint64 singleStep;
+ mutable QSize cachedMinimumSizeHint;
+
+ /**
+ * Parse a string into a number of base monetary units and
+ * return validity.
+ * @note Must return 0 if !valid.
+ */
+ qint64 parse(const QString &text, bool *valid_out=0) const
+ {
+ qint64 val = 0;
+ bool valid = BitcoinUnits::parse(currentUnit, text, &val);
+ if(valid)
+ {
+ if(val < 0 || val > BitcoinUnits::maxMoney())
+ valid = false;
+ }
+ if(valid_out)
+ *valid_out = valid;
+ return valid ? val : 0;
+ }
+
+protected:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
+ {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ if (keyEvent->key() == Qt::Key_Comma)
+ {
+ // Translate a comma into a period
+ QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
+ return QAbstractSpinBox::event(&periodKeyEvent);
+ }
+ }
+ return QAbstractSpinBox::event(event);
+ }
+
+signals:
+ void valueChanged();
+};
+
+#include "bitcoinamountfield.moc"
BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
QWidget(parent),
- amount(0),
- currentUnit(-1)
+ amount(0)
{
- nSingleStep = 100000; // satoshis
-
- amount = new QDoubleSpinBox(this);
+ amount = new AmountSpinBox(this);
amount->setLocale(QLocale::c());
amount->installEventFilter(this);
amount->setMaximumWidth(170);
@@ -40,21 +207,13 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
setFocusProxy(amount);
// If one if the widgets changes, the combined content changes as well
- connect(amount, SIGNAL(valueChanged(QString)), this, SIGNAL(textChanged()));
+ connect(amount, SIGNAL(valueChanged()), this, SIGNAL(valueChanged()));
connect(unit, SIGNAL(currentIndexChanged(int)), this, SLOT(unitChanged(int)));
// Set default based on configuration
unitChanged(unit->currentIndex());
}
-void BitcoinAmountField::setText(const QString &text)
-{
- if (text.isEmpty())
- amount->clear();
- else
- amount->setValue(text.toDouble());
-}
-
void BitcoinAmountField::clear()
{
amount->clear();
@@ -63,16 +222,9 @@ void BitcoinAmountField::clear()
bool BitcoinAmountField::validate()
{
- bool valid = true;
- if (amount->value() == 0.0)
- valid = false;
- else if (!BitcoinUnits::parse(currentUnit, text(), 0))
- valid = false;
- else if (amount->value() > BitcoinUnits::maxAmount(currentUnit))
- valid = false;
-
+ bool valid = false;
+ value(&valid);
setValid(valid);
-
return valid;
}
@@ -84,14 +236,6 @@ void BitcoinAmountField::setValid(bool valid)
amount->setStyleSheet(STYLE_INVALID);
}
-QString BitcoinAmountField::text() const
-{
- if (amount->text().isEmpty())
- return QString();
- else
- return amount->text();
-}
-
bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusIn)
@@ -99,17 +243,6 @@ bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
// Clear invalid flag on focus
setValid(true);
}
- else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
- {
- QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
- if (keyEvent->key() == Qt::Key_Comma)
- {
- // Translate a comma into a period
- QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
- QApplication::sendEvent(object, &periodKeyEvent);
- return true;
- }
- }
return QWidget::eventFilter(object, event);
}
@@ -122,18 +255,12 @@ QWidget *BitcoinAmountField::setupTabChain(QWidget *prev)
qint64 BitcoinAmountField::value(bool *valid_out) const
{
- qint64 val_out = 0;
- bool valid = BitcoinUnits::parse(currentUnit, text(), &val_out);
- if (valid_out)
- {
- *valid_out = valid;
- }
- return val_out;
+ return amount->value(valid_out);
}
void BitcoinAmountField::setValue(qint64 value)
{
- setText(BitcoinUnits::format(currentUnit, value));
+ amount->setValue(value);
}
void BitcoinAmountField::setReadOnly(bool fReadOnly)
@@ -150,28 +277,7 @@ void BitcoinAmountField::unitChanged(int idx)
// Determine new unit ID
int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();
- // Parse current value and convert to new unit
- bool valid = false;
- qint64 currentValue = value(&valid);
-
- currentUnit = newUnit;
-
- // Set max length after retrieving the value, to prevent truncation
- amount->setDecimals(BitcoinUnits::decimals(currentUnit));
- amount->setMaximum(qPow(10, BitcoinUnits::amountDigits(currentUnit)) - qPow(10, -amount->decimals()));
- amount->setSingleStep((double)nSingleStep / (double)BitcoinUnits::factor(currentUnit));
-
- if (valid)
- {
- // If value was valid, re-place it in the widget with the new unit
- setValue(currentValue);
- }
- else
- {
- // If current value is invalid, just clear field
- setText("");
- }
- setValid(true);
+ amount->setDisplayUnit(newUnit);
}
void BitcoinAmountField::setDisplayUnit(int newUnit)
@@ -181,6 +287,5 @@ void BitcoinAmountField::setDisplayUnit(int newUnit)
void BitcoinAmountField::setSingleStep(qint64 step)
{
- nSingleStep = step;
- unitChanged(unit->currentIndex());
+ amount->setSingleStep(step);
}
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index 521a9ed561..c713f5d687 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -8,17 +8,18 @@
#include <QWidget>
QT_BEGIN_NAMESPACE
-class QDoubleSpinBox;
class QValueComboBox;
QT_END_NAMESPACE
+class AmountSpinBox;
+
/** Widget for entering bitcoin amounts.
*/
class BitcoinAmountField: public QWidget
{
Q_OBJECT
- Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true)
+ Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
explicit BitcoinAmountField(QWidget *parent = 0);
@@ -49,20 +50,15 @@ public:
QWidget *setupTabChain(QWidget *prev);
signals:
- void textChanged();
+ void valueChanged();
protected:
/** Intercept focus-in event and ',' key presses */
bool eventFilter(QObject *object, QEvent *event);
private:
- QDoubleSpinBox *amount;
+ AmountSpinBox *amount;
QValueComboBox *unit;
- int currentUnit;
- qint64 nSingleStep;
-
- void setText(const QString &text);
- QString text() const;
private slots:
void unitChanged(int idx);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 6b3aa2a2df..bfca5e8d1a 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -159,10 +159,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
labelEncryptionIcon = new QLabel();
labelConnectionsIcon = new QLabel();
labelBlocksIcon = new QLabel();
- frameBlocksLayout->addStretch();
- frameBlocksLayout->addWidget(unitDisplayControl);
- frameBlocksLayout->addStretch();
- frameBlocksLayout->addWidget(labelEncryptionIcon);
+ if(enableWallet)
+ {
+ frameBlocksLayout->addStretch();
+ frameBlocksLayout->addWidget(unitDisplayControl);
+ frameBlocksLayout->addStretch();
+ frameBlocksLayout->addWidget(labelEncryptionIcon);
+ }
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelConnectionsIcon);
frameBlocksLayout->addStretch();
@@ -269,7 +272,7 @@ void BitcoinGUI::createActions(bool fIsTestnet)
aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin Core"), this);
else
aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin Core"), this);
- aboutAction->setStatusTip(tr("Show information about Bitcoin"));
+ aboutAction->setStatusTip(tr("Show information about Bitcoin Core"));
aboutAction->setMenuRole(QAction::AboutRole);
#if QT_VERSION < 0x050000
aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
@@ -475,13 +478,13 @@ void BitcoinGUI::createTrayIcon(bool fIsTestnet)
if (!fIsTestnet)
{
- trayIcon->setToolTip(tr("Bitcoin client"));
- trayIcon->setIcon(QIcon(":/icons/toolbar"));
+ trayIcon->setToolTip(tr("Bitcoin Core client"));
+ trayIcon->setIcon(QIcon(":/icons/bitcoin"));
}
else
{
- trayIcon->setToolTip(tr("Bitcoin client") + " " + tr("[testnet]"));
- trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
+ trayIcon->setToolTip(tr("Bitcoin Core client") + " " + tr("[testnet]"));
+ trayIcon->setIcon(QIcon(":/icons/bitcoin_testnet"));
}
trayIcon->show();
@@ -780,11 +783,7 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
buttons = QMessageBox::Ok;
- // Ensure we get users attention, but only if main window is visible
- // as we don't want to pop up the main window for messages that happen before
- // initialization is finished.
- if(!(style & CClientUIInterface::NOSHOWGUI))
- showNormalIfMinimized();
+ showNormalIfMinimized();
QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
int r = mBox.exec();
if (ret != NULL)
@@ -921,6 +920,8 @@ void BitcoinGUI::setEncryptionStatus(int status)
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
+ if(!clientModel)
+ return;
// activateWindow() (sometimes) helps with keyboard focus on Windows
if (isHidden())
{
@@ -1012,7 +1013,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel()
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
}
-/** So that it responds to left-button clicks */
+/** So that it responds to button clicks */
void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
{
onDisplayUnitsClicked(event->pos());
@@ -1029,10 +1030,6 @@ void UnitDisplayStatusBarControl::createContextMenu()
menu->addAction(menuAction);
}
connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
-
- // what happens on right click.
- setContextMenuPolicy(Qt::CustomContextMenu);
- connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(onDisplayUnitsClicked(const QPoint&)));
}
/** Lets the control know about the Options Model (and its signals) */
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index e852c468a8..3b4b40aae3 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -38,6 +38,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Bind to given address and always listen on it. Use [host]:port notation for "
"IPv6"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Bind to given address and whitelist peers connecting to it. Use [host]:port "
+"notation for IPv6"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Bind to given address to listen for JSON-RPC connections. Use [host]:port "
"notation for IPv6. This option can be specified multiple times (default: "
"bind to all interfaces)"),
@@ -48,8 +51,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Continuously rate-limit free transactions to <n>*1000 bytes per minute "
"(default:15)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Delete all wallet transactions and only recover those part of the blockchain "
-"through -rescan on startup"),
+"Create new files with system default permissions, instead of umask 077 (only "
+"effective with disabled wallet functionality)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Delete all wallet transactions and only recover those parts of the "
+"blockchain through -rescan on startup"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Distributed under the MIT/X11 software license, see the accompanying file "
"COPYING or <http://www.opensource.org/licenses/mit-license.php>."),
@@ -66,6 +72,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: This transaction requires a transaction fee of at least %s because of "
"its amount, complexity, or use of recently received funds!"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Error: Unsupported argument -socks found. Setting SOCKS version isn't "
+"possible anymore, only SOCKS5 proxies are supported."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Execute command when a network tx respends wallet tx input (%s=respend TxID, "
"%t=wallet TxID)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -102,6 +111,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Output debugging information (default: 0, supplying <category> is optional)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Query for peer addresses via DNS lookup, if low on addresses (default: 1 "
+"unless -connect)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Set the number of script verification threads (%u to %d, 0 = auto, <0 = "
@@ -127,7 +139,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"pay if you send a transaction."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: Please check that your computer's date and time are correct! If "
-"your clock is wrong Bitcoin will not work properly."),
+"your clock is wrong Bitcoin Core will not work properly."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: The network does not appear to fully agree! Some miners appear to "
"be experiencing issues."),
@@ -141,6 +153,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"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."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Whitelist peers connecting from the given netmask or ip. Can be specified "
+"multiple times."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Whitelisted peers cannot be DoS banned and their transactions are always "
+"relayed, even if they are already in the mempool, useful e.g. for a gateway"),
QT_TRANSLATE_NOOP("bitcoin-core", "(default: 1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "(default: wallet.dat)"),
QT_TRANSLATE_NOOP("bitcoin-core", "<category> can be:"),
@@ -148,14 +166,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"),
QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"),
QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Always query for peer addresses via DNS lookup (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"),
QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -whitebind address: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS proxy"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS5 proxy"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connection options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) 2009-%i The Bitcoin Core Developers"),
@@ -172,7 +192,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error initializing wallet database environmen
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet corrupted"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Bitcoin"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Bitcoin Core"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"),
@@ -191,7 +211,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write to coin database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"),
QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in BTC/kB) to add to transactions you send (default: %s)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Force safe mode (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"),
@@ -210,6 +229,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=<amount>: '%s'")
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most <n> unconnectable blocks in memory (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Limit size of signature cache to <n> entries (default: 50000)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: 8333 or testnet: 18333)"),
@@ -221,6 +241,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Maintain a full transaction index (default: 0
QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most <n> connections to peers (default: 125)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Need to specify a port with -whitebind: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Node relay options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."),
QT_TRANSLATE_NOOP("bitcoin-core", "Only accept block chain matching built-in checkpoints (default: 1)"),
@@ -236,11 +257,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Randomly drop 1 of every <n> network messages
QT_TRANSLATE_NOOP("bitcoin-core", "Randomly fuzz 1 of every <n> network messages"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild block chain index from current blk000??.dat files"),
QT_TRANSLATE_NOOP("bitcoin-core", "Relay and mine data carrier transactions (default: 1)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Relay non-P2SH multisig (default: 1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Run a thread to flush wallet periodically (default: 1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Select SOCKS version for -proxy (4 or 5, default: 5)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"),
QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"),
@@ -251,7 +272,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: 0)"
QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: 4)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Sets the DB_PRIVATE flag in the wallet db environment (default: 1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Show all debugging options (usage: --help -help-debug)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Show benchmark information (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Signing transaction failed"),
QT_TRANSLATE_NOOP("bitcoin-core", "Specify configuration file (default: bitcoin.conf)"),
@@ -272,7 +292,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amount too small"),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amounts must be positive"),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"),
@@ -283,11 +302,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin Core to complete"),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Deprecated argument -debugnet ignored, use -debug=net"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -benchmark ignored, use -debug=bench."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -debugnet ignored, use -debug=net."),
QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."),
QT_TRANSLATE_NOOP("bitcoin-core", "on startup"),
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index bbc9b2e5af..6f506d3f25 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -4,6 +4,8 @@
#include "bitcoinunits.h"
+#include "core.h"
+
#include <QStringList>
BitcoinUnits::BitcoinUnits(QObject *parent):
@@ -61,8 +63,8 @@ QString BitcoinUnits::description(int unit)
switch(unit)
{
case BTC: return QString("Bitcoins");
- case mBTC: return QString("Milli-Bitcoins (1 / 1,000)");
- case uBTC: return QString("Micro-Bitcoins (1 / 1,000,000)");
+ case mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");
+ case uBTC: return QString("Micro-Bitcoins (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
default: return QString("???");
}
}
@@ -78,28 +80,6 @@ qint64 BitcoinUnits::factor(int unit)
}
}
-qint64 BitcoinUnits::maxAmount(int unit)
-{
- switch(unit)
- {
- case BTC: return Q_INT64_C(21000000);
- case mBTC: return Q_INT64_C(21000000000);
- case uBTC: return Q_INT64_C(21000000000000);
- default: return 0;
- }
-}
-
-int BitcoinUnits::amountDigits(int unit)
-{
- switch(unit)
- {
- case BTC: return 8; // 21,000,000 (# digits, without commas)
- case mBTC: return 11; // 21,000,000,000
- case uBTC: return 14; // 21,000,000,000,000
- default: return 0;
- }
-}
-
int BitcoinUnits::decimals(int unit)
{
switch(unit)
@@ -111,7 +91,7 @@ int BitcoinUnits::decimals(int unit)
}
}
-QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
+QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle separators)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
@@ -125,11 +105,20 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
QString quotient_str = QString::number(quotient);
QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
- // Right-trim excess zeros after the decimal point
- int nTrim = 0;
- for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
- ++nTrim;
- remainder_str.chop(nTrim);
+ // Use SI-stule separators as these are locale indendent and can't be
+ // confused with the decimal marker. Rule is to use a thin space every
+ // three digits on *both* sides of the decimal point - but only if there
+ // are five or more digits
+ QChar thin_sp(THIN_SP_CP);
+ int q_size = quotient_str.size();
+ if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
+ for (int i = 3; i < q_size; i += 3)
+ quotient_str.insert(q_size - i, thin_sp);
+
+ int r_size = remainder_str.size();
+ if (separators == separatorAlways || (separators == separatorStandard && r_size > 4))
+ for (int i = 3, adj = 0; i < r_size ; i += 3, adj++)
+ remainder_str.insert(i + adj, thin_sp);
if (n < 0)
quotient_str.insert(0, '-');
@@ -138,17 +127,43 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
return quotient_str + QString(".") + remainder_str;
}
-QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
+
+// TODO: Review all remaining calls to BitcoinUnits::formatWithUnit to
+// TODO: determine whether the output is used in a plain text context
+// TODO: or an HTML context (and replace with
+// TODO: BtcoinUnits::formatHtmlWithUnit in the latter case). Hopefully
+// TODO: there aren't instances where the result could be used in
+// TODO: either context.
+
+// NOTE: Using formatWithUnit in an HTML context risks wrapping
+// quantities at the thousands separator. More subtly, it also results
+// in a standard space rather than a thin space, due to a bug in Qt's
+// XML whitespace canonicalisation
+//
+// Please take care to use formatHtmlWithUnit instead, when
+// appropriate.
+
+QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators)
+{
+ return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
+}
+
+QString BitcoinUnits::formatHtmlWithUnit(int unit, qint64 amount, bool plussign, SeparatorStyle separators)
{
- return format(unit, amount, plussign) + QString(" ") + name(unit);
+ QString str(formatWithUnit(unit, amount, plussign, separators));
+ str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
+ return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
}
+
bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
if(!valid(unit) || value.isEmpty())
return false; // Refuse to parse invalid unit or empty string
int num_decimals = decimals(unit);
- QStringList parts = value.split(".");
+
+ // Ignore spaces and thin spaces when parsing
+ QStringList parts = removeSpaces(value).split(".");
if(parts.size() > 2)
{
@@ -215,3 +230,8 @@ QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
}
return QVariant();
}
+
+qint64 BitcoinUnits::maxMoney()
+{
+ return MAX_MONEY;
+}
diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h
index da34ed8976..be9dca6012 100644
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -8,6 +8,37 @@
#include <QAbstractListModel>
#include <QString>
+// U+2009 THIN SPACE = UTF-8 E2 80 89
+#define REAL_THIN_SP_CP 0x2009
+#define REAL_THIN_SP_UTF8 "\xE2\x80\x89"
+#define REAL_THIN_SP_HTML "&thinsp;"
+
+// U+200A HAIR SPACE = UTF-8 E2 80 8A
+#define HAIR_SP_CP 0x200A
+#define HAIR_SP_UTF8 "\xE2\x80\x8A"
+#define HAIR_SP_HTML "&#8202;"
+
+// U+2006 SIX-PER-EM SPACE = UTF-8 E2 80 86
+#define SIXPEREM_SP_CP 0x2006
+#define SIXPEREM_SP_UTF8 "\xE2\x80\x86"
+#define SIXPEREM_SP_HTML "&#8198;"
+
+// U+2007 FIGURE SPACE = UTF-8 E2 80 87
+#define FIGURE_SP_CP 0x2007
+#define FIGURE_SP_UTF8 "\xE2\x80\x87"
+#define FIGURE_SP_HTML "&#8199;"
+
+// QMessageBox seems to have a bug whereby it doesn't display thin/hair spaces
+// correctly. Workaround is to display a space in a small font. If you
+// change this, please test that it doesn't cause the parent span to start
+// wrapping.
+#define HTML_HACK_SP "<span style='white-space: nowrap; font-size: 6pt'> </span>"
+
+// Define THIN_SP_* variables to be our preferred type of thin space
+#define THIN_SP_CP REAL_THIN_SP_CP
+#define THIN_SP_UTF8 REAL_THIN_SP_UTF8
+#define THIN_SP_HTML HTML_HACK_SP
+
/** Bitcoin unit definitions. Encapsulates parsing and formatting
and serves as list model for drop-down selection boxes.
*/
@@ -28,6 +59,13 @@ public:
uBTC
};
+ enum SeparatorStyle
+ {
+ separatorNever,
+ separatorStandard,
+ separatorAlways
+ };
+
//! @name Static API
//! Unit conversion and formatting
///@{
@@ -44,16 +82,13 @@ public:
static QString description(int unit);
//! Number of Satoshis (1e-8) per unit
static qint64 factor(int unit);
- //! Max amount per unit
- static qint64 maxAmount(int unit);
- //! Number of amount digits (to represent max number of coins)
- static int amountDigits(int unit);
//! Number of decimals left
static int decimals(int unit);
//! Format as string
- static QString format(int unit, qint64 amount, bool plussign=false);
+ static QString format(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
//! Format as string (with unit)
- static QString formatWithUnit(int unit, qint64 amount, bool plussign=false);
+ static QString formatWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
+ static QString formatHtmlWithUnit(int unit, qint64 amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
//! Parse string to coin amount
static bool parse(int unit, const QString &value, qint64 *val_out);
//! Gets title for amount column including current display unit if optionsModel reference available */
@@ -71,6 +106,19 @@ public:
QVariant data(const QModelIndex &index, int role) const;
///@}
+ static QString removeSpaces(QString text)
+ {
+ text.remove(' ');
+ text.remove(QChar(THIN_SP_CP));
+#if (THIN_SP_CP != REAL_THIN_SP_CP)
+ text.remove(QChar(REAL_THIN_SP_CP));
+#endif
+ return text;
+ }
+
+ //! Return maximum number of base units (Satoshis)
+ static qint64 maxMoney();
+
private:
QList<BitcoinUnits::Unit> unitlist;
};
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index b4ddda3eaa..7b30f8de09 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -225,7 +225,7 @@ void CoinControlDialog::showMenu(const QPoint &point)
// context menu action: copy amount
void CoinControlDialog::copyAmount()
{
- GUIUtil::setClipboard(contextMenuItem->text(COLUMN_AMOUNT));
+ GUIUtil::setClipboard(BitcoinUnits::removeSpaces(contextMenuItem->text(COLUMN_AMOUNT)));
}
// context menu action: copy label
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 1f535a4a62..47ed4c8bc6 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -452,16 +452,6 @@
</layout>
</item>
<item>
- <widget class="QCheckBox" name="displayAddresses">
- <property name="toolTip">
- <string>Whether to show Bitcoin addresses in the transaction list or not.</string>
- </property>
- <property name="text">
- <string>&amp;Display addresses in transaction list</string>
- </property>
- </widget>
- </item>
- <item>
<layout class="QHBoxLayout" name="horizontalLayout_3_Display">
<item>
<widget class="QLabel" name="thirdPartyTxUrlsLabel">
diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui
index 8784da5f3e..7784a862d7 100644
--- a/src/qt/forms/overviewpage.ui
+++ b/src/qt/forms/overviewpage.ui
@@ -13,8 +13,8 @@
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout" name="topLayout">
- <item>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="0" column="0" colspan="2">
<widget class="QLabel" name="labelAlerts">
<property name="visible">
<bool>false</bool>
@@ -30,7 +30,7 @@
</property>
</widget>
</item>
- <item>
+ <item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -46,374 +46,344 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_7">
- <item>
- <widget class="QLabel" name="label_5">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Wallet</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelWalletStatus">
- <property name="toolTip">
- <string>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.</string>
- </property>
- <property name="styleSheet">
- <string notr="true">QLabel { color: red; }</string>
- </property>
- <property name="text">
- <string notr="true">(out of sync)</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- </layout>
+ <widget class="QLabel" name="label_5">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Balances</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelWalletStatus">
+ <property name="cursor">
+ <cursorShape>WhatsThisCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>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.</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QLabel { color: red; }</string>
+ </property>
+ <property name="text">
+ <string notr="true">(out of sync)</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_8">
- <item>
- <widget class="QLabel" name="labelWatchonly">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Watchonly:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <layout class="QFormLayout" name="formLayout_2">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <property name="horizontalSpacing">
- <number>12</number>
- </property>
- <property name="verticalSpacing">
- <number>12</number>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Available:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="labelBalance">
- <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 spendable balance</string>
- </property>
- <property name="text">
- <string notr="true">0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Pending:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="labelUnconfirmed">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="toolTip">
- <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>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="labelImmatureText">
- <property name="text">
- <string>Immature:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="labelImmature">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Mined balance that has not yet matured</string>
- </property>
- <property name="text">
- <string notr="true">0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </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>
- <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="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="spacing">
+ <number>12</number>
+ </property>
+ <item row="2" column="2">
+ <widget class="QLabel" name="labelWatchPending">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Unconfirmed transactions to watch-only addresses</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
- <property name="horizontalSpacing">
- <number>12</number>
- </property>
- <property name="verticalSpacing">
- <number>12</number>
- </property>
- <item row="0" column="1">
- <widget class="QLabel" name="labelWatchAvailable">
- <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 balance in watchonly addresses</string>
- </property>
- <property name="text">
- <string>0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="labelWatchPending">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Unconfirmed transactions to watchonly addresses</string>
- </property>
- <property name="text">
- <string>0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="labelWatchImmature">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Mined balance in watchonly addresses that has not yet matured</string>
- </property>
- <property name="text">
- <string>0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </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="lineWatchBalance">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>140</width>
- <height>0</height>
- </size>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="labelWatchTotal">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="toolTip">
- <string>Current total balance in watchonly addresses</string>
- </property>
- <property name="text">
- <string>0 BTC</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- </layout>
+ <item row="2" column="1">
+ <widget class="QLabel" name="labelUnconfirmed">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <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.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
</item>
- <item>
- <spacer name="horizontalSpacer_3">
+ <item row="3" column="2">
+ <widget class="QLabel" name="labelWatchImmature">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Mined balance in watch-only addresses that has not yet matured</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="Line" name="lineWatchBalance">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>140</width>
+ <height>0</height>
+ </size>
+ </property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="labelTotalText">
+ <property name="text">
+ <string>Total:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="labelImmature">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Mined balance that has not yet matured</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
+ <width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="labelImmatureText">
+ <property name="text">
+ <string>Immature:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" 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.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QLabel" name="labelWatchTotal">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="toolTip">
+ <string>Current total balance in watch-only addresses</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="labelWatchonly">
+ <property name="text">
+ <string>Watch-only:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelBalanceText">
+ <property name="text">
+ <string>Available:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="labelBalance">
+ <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 spendable balance</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="labelWatchAvailable">
+ <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 balance in watch-only addresses</string>
+ </property>
+ <property name="text">
+ <string notr="true">0.000 000 00 BTC</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="labelPendingText">
+ <property name="text">
+ <string>Pending:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="labelSpendable">
+ <property name="text">
+ <string>Spendable:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
</layout>
@@ -449,13 +419,22 @@
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_4">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
<property name="text">
- <string>&lt;b&gt;Recent transactions&lt;/b&gt;</string>
+ <string>Recent transactions</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelTransactionsStatus">
+ <property name="cursor">
+ <cursorShape>WhatsThisCursor</cursorShape>
+ </property>
<property name="toolTip">
<string>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.</string>
</property>
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index 7158b65c2d..b9b90aa846 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -428,7 +428,7 @@
</item>
</layout>
</widget>
- <widget class="QWidget" name="tab">
+ <widget class="QWidget" name="tab_nettraffic">
<attribute name="title">
<string>&amp;Network Traffic</string>
</attribute>
@@ -683,6 +683,19 @@
<string>&amp;Peers</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" rowspan="2">
+ <widget class="QTableView" name="peerWidget">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
<item row="0" column="1">
<widget class="QLabel" name="peerHeading">
<property name="sizePolicy">
@@ -691,262 +704,377 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="text">
- <string>Select a peer to view detailed information.</string>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>32</height>
+ </size>
</property>
- <property name="margin">
- <number>3</number>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
</property>
- </widget>
- </item>
- <item row="0" column="0" rowspan="2">
- <widget class="QTableView" name="peerWidget">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
</property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
+ <property name="text">
+ <string>Select a peer to view detailed information.</string>
</property>
- <property name="editTriggers">
- <set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
+ <property name="alignment">
+ <set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
- <property name="sortingEnabled">
+ <property name="wordWrap">
<bool>true</bool>
</property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="detailWidget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
</property>
<layout class="QGridLayout" name="gridLayout_3">
- <property name="leftMargin">
- <number>3</number>
- </property>
- <item row="12" column="0">
- <widget class="QLabel" name="label_21">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_23">
<property name="text">
- <string>Version:</string>
+ <string>Direction</string>
</property>
</widget>
</item>
- <item row="11" column="1">
- <widget class="QLabel" name="peerPingTime">
+ <item row="0" column="2">
+ <widget class="QLabel" name="peerDirection">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_19">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_21">
<property name="text">
- <string>Last Receive:</string>
+ <string>Version</string>
</property>
</widget>
</item>
- <item row="14" column="0">
- <widget class="QLabel" name="label_28">
+ <item row="1" column="2">
+ <widget class="QLabel" name="peerVersion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
- <string>User Agent:</string>
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="12" column="1">
- <widget class="QLabel" name="peerVersion">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_28">
<property name="text">
- <string>N/A</string>
+ <string>User Agent</string>
</property>
</widget>
</item>
- <item row="8" column="1">
- <widget class="QLabel" name="peerConnTime">
- <property name="minimumSize">
- <size>
- <width>160</width>
- <height>0</height>
- </size>
+ <item row="2" column="2">
+ <widget class="QLabel" name="peerSubversion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="11" column="0">
- <widget class="QLabel" name="label_26">
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
<property name="text">
- <string>Ping Time:</string>
+ <string>Services</string>
</property>
</widget>
</item>
- <item row="5" column="1">
- <widget class="QLabel" name="peerLastRecv">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="3" column="2">
+ <widget class="QLabel" name="peerServices">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="label_22">
- <property name="text">
- <string>Connection Time:</string>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="6" column="1">
- <widget class="QLabel" name="peerBytesSent">
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_25">
<property name="text">
- <string>N/A</string>
+ <string>Sync Node</string>
</property>
</widget>
</item>
- <item row="14" column="1">
- <widget class="QLabel" name="peerSubversion">
+ <item row="4" column="2">
+ <widget class="QLabel" name="peerSyncNode">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
- <string>Starting Height:</string>
+ <string>Starting Height</string>
</property>
</widget>
</item>
- <item row="7" column="1">
- <widget class="QLabel" name="peerBytesRecv">
+ <item row="5" column="2">
+ <widget class="QLabel" name="peerHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
<item row="6" column="0">
- <widget class="QLabel" name="label_18">
+ <widget class="QLabel" name="label_27">
<property name="text">
- <string>Bytes Sent:</string>
+ <string>Sync Height</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QLabel" name="peerSyncHeight">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0">
- <widget class="QLabel" name="label_20">
+ <widget class="QLabel" name="label_24">
<property name="text">
- <string>Bytes Received:</string>
+ <string>Ban Score</string>
</property>
</widget>
</item>
- <item row="15" column="1">
- <widget class="QLabel" name="peerHeight">
+ <item row="7" column="2">
+ <widget class="QLabel" name="peerBanScore">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="16" column="0">
- <widget class="QLabel" name="label_24">
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_22">
<property name="text">
- <string>Ban Score:</string>
+ <string>Connection Time</string>
</property>
</widget>
</item>
- <item row="16" column="1">
- <widget class="QLabel" name="peerBanScore">
+ <item row="8" column="2">
+ <widget class="QLabel" name="peerConnTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="17" column="0">
- <widget class="QLabel" name="label_23">
+ <item row="9" column="0">
+ <widget class="QLabel" name="label_15">
<property name="text">
- <string>Direction:</string>
+ <string>Last Send</string>
</property>
</widget>
</item>
- <item row="17" column="1">
- <widget class="QLabel" name="peerDirection">
+ <item row="9" column="2">
+ <widget class="QLabel" name="peerLastSend">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="19" column="0">
- <widget class="QLabel" name="label_25">
+ <item row="10" column="0">
+ <widget class="QLabel" name="label_19">
<property name="text">
- <string>Sync Node:</string>
+ <string>Last Receive</string>
</property>
</widget>
</item>
- <item row="19" column="1">
- <widget class="QLabel" name="peerSyncNode">
+ <item row="10" column="2">
+ <widget class="QLabel" name="peerLastRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_15">
+ <item row="11" column="0">
+ <widget class="QLabel" name="label_18">
<property name="text">
- <string>Last Send:</string>
+ <string>Bytes Sent</string>
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
+ <item row="11" column="2">
+ <widget class="QLabel" name="peerBytesSent">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
- <string>Services:</string>
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_27">
+ <item row="12" column="0">
+ <widget class="QLabel" name="label_20">
<property name="text">
- <string>IP Address/port:</string>
+ <string>Bytes Received</string>
</property>
</widget>
</item>
- <item row="3" column="1">
- <widget class="QLabel" name="peerLastSend">
+ <item row="12" column="2">
+ <widget class="QLabel" name="peerBytesRecv">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QLabel" name="peerServices">
+ <item row="13" column="0">
+ <widget class="QLabel" name="label_26">
<property name="text">
- <string>N/A</string>
+ <string>Ping Time</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="peerAddr">
+ <item row="13" column="2">
+ <widget class="QLabel" name="peerPingTime">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
<property name="text">
<string>N/A</string>
</property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
</widget>
</item>
- <item row="20" column="0">
- <widget class="QWidget" name="widget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <item row="14" column="1">
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
</item>
</layout>
</widget>
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index 696761e234..5ae4bc833d 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -23,10 +23,6 @@ static const int STATUSBAR_ICONSIZE = 16;
#define COLOR_NEGATIVE QColor(255, 0, 0)
/* Transaction list -- bare address (without label) */
#define COLOR_BAREADDRESS QColor(140, 140, 140)
-/* Transaction list -- has conflicting transactions */
-#define COLOR_HASCONFLICTING QColor(255, 255, 255)
-/* Transaction list -- has conflicting transactions - background */
-#define COLOR_HASCONFLICTING_BG QColor(192, 0, 0)
/* Tooltips longer than this (in characters) are converted into rich text,
so that they can be word-wrapped.
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 60a131df7e..7837e4229e 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -63,6 +63,13 @@
static boost::filesystem::detail::utf8_codecvt_facet utf8;
#endif
+#if defined(Q_OS_MAC)
+extern double NSAppKitVersionNumber;
+#if !defined(NSAppKitVersionNumber10_9)
+#define NSAppKitVersionNumber10_9 1265
+#endif
+#endif
+
namespace GUIUtil {
QString dateTimeStr(const QDateTime &date)
@@ -117,6 +124,10 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
SendCoinsRecipient rv;
rv.address = uri.path();
+ // Trim any following forward slash which may have been added by the OS
+ if (rv.address.endsWith("/")) {
+ rv.address.truncate(rv.address.length() - 1);
+ }
rv.amount = 0;
#if QT_VERSION < 0x050000
@@ -187,7 +198,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
if (info.amount)
{
- ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount));
+ ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount, false, BitcoinUnits::separatorNever));
paramCount++;
}
@@ -376,6 +387,26 @@ ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *pa
}
+void SubstituteFonts()
+{
+#if defined(Q_OS_MAC)
+// Background:
+// OSX's default font changed in 10.9 and QT is unable to find it with its
+// usual fallback methods when building against the 10.7 sdk or lower.
+// The 10.8 SDK added a function to let it find the correct fallback font.
+// If this fallback is not properly loaded, some characters may fail to
+// render correctly.
+//
+// Solution: If building with the 10.7 SDK or lower and the user's platform
+// is 10.9 or higher at runtime, substitute the correct font. This needs to
+// happen before the QApplication is created.
+#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
+ if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_9)
+ QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
+#endif
+#endif
+}
+
bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
{
if(evt->type() == QEvent::ToolTipChange)
@@ -804,4 +835,9 @@ QString formatServicesStr(uint64_t mask)
return QObject::tr("None");
}
+QString formatPingTime(double dPingTime)
+{
+ return dPingTime == 0 ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10));
+}
+
} // namespace GUIUtil
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 45c78b4e14..83739a5f13 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -106,6 +106,10 @@ namespace GUIUtil
representation if needed. This assures that Qt can word-wrap long tooltip messages.
Tooltips longer than the provided size threshold (in characters) are wrapped.
*/
+
+ // Replace invalid default fonts with known good ones
+ void SubstituteFonts();
+
class ToolTipToRichTextFilter : public QObject
{
Q_OBJECT
@@ -178,6 +182,9 @@ namespace GUIUtil
/* Format CNodeStats.nServices bitmask into a user-readable string */
QString formatServicesStr(uint64_t mask);
+
+ /* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/
+ QString formatPingTime(double dPingTime);
} // namespace GUIUtil
#endif // GUIUTIL_H
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index 3e99e941a6..d469c9a0bd 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -181,8 +181,8 @@ void Intro::pickDataDirectory()
TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir));
break;
} catch(fs::filesystem_error &e) {
- QMessageBox::critical(0, tr("Bitcoin"),
- tr("Error: Specified data directory \"%1\" can not be created.").arg(dataDir));
+ QMessageBox::critical(0, tr("Bitcoin Core"),
+ tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));
/* fall through, back to choosing screen */
}
}
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 4b541eabe9..a527602b5a 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -2,50 +2,6 @@
<!DOCTYPE TS>
<TS version="2.1" language="en">
<context>
- <name>AboutDialog</name>
- <message>
- <location filename="../forms/aboutdialog.ui" line="+14"/>
- <source>About Bitcoin Core</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+39"/>
- <source>&lt;b&gt;Bitcoin Core&lt;/b&gt; version</source>
- <translation type="unfinished"></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>
-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="../utilitydialog.cpp" line="+29"/>
- <source>Copyright</source>
- <translation>Copyright</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>The Bitcoin Core developers</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+12"/>
- <location line="+2"/>
- <source>(%1-bit)</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-<context>
<name>AddressBookPage</name>
<message>
<location filename="../forms/addressbookpage.ui" line="+30"/>
@@ -164,7 +120,7 @@ This product includes software developed by the OpenSSL Project for use in the O
</message>
<message>
<location line="+1"/>
- <source>There was an error trying to save the address list to %1.</source>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -209,12 +165,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Repeat new passphrase</translation>
</message>
<message>
- <location filename="../askpassphrasedialog.cpp" line="+40"/>
- <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>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;.</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location filename="../askpassphrasedialog.cpp" line="+41"/>
<source>Encrypt wallet</source>
<translation>Encrypt wallet</translation>
</message>
@@ -281,7 +232,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Wallet encrypted</translation>
</message>
<message>
- <location line="-56"/>
+ <location line="-135"/>
+ <source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+79"/>
<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>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.</translation>
</message>
@@ -330,27 +286,27 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+294"/>
+ <location filename="../bitcoingui.cpp" line="+300"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+335"/>
+ <location line="+339"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-407"/>
+ <location line="-411"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
<message>
- <location line="-136"/>
+ <location line="-142"/>
<source>Node</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+137"/>
+ <location line="+143"/>
<source>Show general overview of wallet</source>
<translation>Show general overview of wallet</translation>
</message>
@@ -375,12 +331,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Quit application</translation>
</message>
<message>
- <location line="+7"/>
- <source>Show information about Bitcoin</source>
- <translation>Show information about Bitcoin</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+10"/>
<location line="+2"/>
<source>About &amp;Qt</source>
<translation>About &amp;Qt</translation>
@@ -426,7 +377,13 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+325"/>
+ <location line="+168"/>
+ <location line="+5"/>
+ <source>Bitcoin Core client</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+156"/>
<source>Importing blocks from disk...</source>
<translation>Importing blocks from disk...</translation>
</message>
@@ -436,7 +393,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
- <location line="-405"/>
+ <location line="-409"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -471,17 +428,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Verify message...</translation>
</message>
<message>
- <location line="+440"/>
+ <location line="+437"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="-652"/>
+ <location line="-655"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
<message>
- <location line="+145"/>
+ <location line="+151"/>
<source>&amp;Send</source>
<translation>&amp;Send</translation>
</message>
@@ -491,7 +448,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Receive</translation>
</message>
<message>
- <location line="+46"/>
+ <location line="+33"/>
+ <source>Show information about Bitcoin Core</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
<location line="+2"/>
<source>&amp;Show / Hide</source>
<translation>&amp;Show / Hide</translation>
@@ -537,18 +499,18 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="-283"/>
- <location line="+375"/>
+ <location line="-289"/>
+ <location line="+386"/>
<source>[testnet]</source>
<translation>[testnet]</translation>
</message>
<message>
- <location line="-400"/>
+ <location line="-411"/>
<source>Bitcoin Core</source>
<translation type="unfinished">Bitcoin Core</translation>
</message>
<message>
- <location line="+162"/>
+ <location line="+168"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
@@ -583,14 +545,8 @@ This product includes software developed by the OpenSSL Project for use in the O
<source>Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+159"/>
- <location line="+5"/>
- <source>Bitcoin client</source>
- <translation>Bitcoin client</translation>
- </message>
<message numerus="yes">
- <location line="+142"/>
+ <location line="+310"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -603,17 +559,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>No block source available...</translation>
</message>
<message>
- <location line="+12"/>
- <source>Processed %1 of %2 (estimated) blocks of transaction history.</source>
- <translation>Processed %1 of %2 (estimated) blocks of transaction history.</translation>
- </message>
- <message>
- <location line="+4"/>
+ <location line="+10"/>
<source>Processed %1 blocks of transaction history.</source>
<translation>Processed %1 blocks of transaction history.</translation>
</message>
<message numerus="yes">
- <location line="+27"/>
+ <location line="+26"/>
<source>%n hour(s)</source>
<translation>
<numerusform>%n hour</numerusform>
@@ -691,7 +642,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Catching up...</translation>
</message>
<message>
- <location line="+130"/>
+ <location line="+126"/>
<source>Sent transaction</source>
<translation>Sent transaction</translation>
</message>
@@ -723,16 +674,11 @@ Address: %4
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <location filename="../bitcoin.cpp" line="+447"/>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
- </message>
</context>
<context>
<name>ClientModel</name>
<message>
- <location filename="../clientmodel.cpp" line="+137"/>
+ <location filename="../clientmodel.cpp" line="+138"/>
<source>Network Alert</source>
<translation>Network Alert</translation>
</message>
@@ -771,7 +717,7 @@ Address: %4
</message>
<message>
<location line="+32"/>
- <source>Low Output:</source>
+ <source>Dust:</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -830,7 +776,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../coincontroldialog.cpp" line="+41"/>
+ <location filename="../coincontroldialog.cpp" line="+43"/>
<source>Copy address</source>
<translation type="unfinished">Copy address</translation>
</message>
@@ -887,7 +833,7 @@ Address: %4
</message>
<message>
<location line="+1"/>
- <source>Copy low output</source>
+ <source>Copy dust</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -896,17 +842,17 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+332"/>
+ <location line="+333"/>
<source>highest</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+0"/>
<source>higher</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+0"/>
<source>high</source>
<translation type="unfinished"></translation>
</message>
@@ -916,17 +862,18 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+0"/>
+ <location line="+12"/>
<source>medium</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
+ <location line="-11"/>
<source>low-medium</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+0"/>
<source>low</source>
<translation type="unfinished"></translation>
</message>
@@ -936,27 +883,27 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+11"/>
<source>lowest</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+10"/>
<source>(%1 locked)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+32"/>
+ <location line="+28"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+141"/>
- <source>Dust</source>
+ <location line="+162"/>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+0"/>
+ <location line="-28"/>
<source>yes</source>
<translation type="unfinished"></translation>
</message>
@@ -966,7 +913,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+16"/>
<source>This label turns red, if the transaction size is greater than 1000 bytes.</source>
<translation type="unfinished"></translation>
</message>
@@ -997,23 +944,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <location line="+4"/>
- <source>This means a fee of at least %1 is required.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-3"/>
- <source>Amounts below 0.546 times the minimum relay fee are shown as dust.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
- <source>This label turns red, if the change is smaller than %1.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+43"/>
+ <location line="+50"/>
<location line="+61"/>
<source>(no label)</source>
<translation type="unfinished">(no label)</translation>
@@ -1128,12 +1059,7 @@ Address: %4
<context>
<name>HelpMessageDialog</name>
<message>
- <location filename="../forms/helpmessagedialog.ui" line="+19"/>
- <source>Bitcoin Core - Command-line options</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../utilitydialog.cpp" line="+24"/>
+ <location filename="../utilitydialog.cpp" line="+29"/>
<source>Bitcoin Core</source>
<translation type="unfinished">Bitcoin Core</translation>
</message>
@@ -1143,7 +1069,23 @@ Address: %4
<translation type="unfinished">version</translation>
</message>
<message>
+ <location line="+5"/>
<location line="+2"/>
+ <source>(%1-bit)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>About Bitcoin Core</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Command-line options</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Usage:</source>
<translation type="unfinished">Usage:</translation>
</message>
@@ -1217,13 +1159,13 @@ Address: %4
</message>
<message>
<location filename="../intro.cpp" line="+82"/>
- <source>Bitcoin</source>
- <translation type="unfinished">Bitcoin</translation>
+ <source>Bitcoin Core</source>
+ <translation type="unfinished">Bitcoin Core</translation>
</message>
<message>
<location line="+1"/>
- <source>Error: Specified data directory &quot;%1&quot; can not be created.</source>
- <translation type="unfinished">Error: Specified data directory &quot;%1&quot; can not be created.</translation>
+ <source>Error: Specified data directory &quot;%1&quot; cannot be created.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+24"/>
@@ -1318,6 +1260,16 @@ Address: %4
</message>
<message>
<location line="+160"/>
+ <source>Accept connections from outside</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Allow incoming connections</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
<source>Connect to the Bitcoin network through a SOCKS proxy.</source>
<translation type="unfinished"></translation>
</message>
@@ -1332,7 +1284,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+194"/>
+ <location line="+164"/>
<location line="+13"/>
<source>Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
<translation type="unfinished"></translation>
@@ -1358,7 +1310,7 @@ Address: %4
<translation>&amp;Reset Options</translation>
</message>
<message>
- <location line="-337"/>
+ <location line="-317"/>
<source>&amp;Network</source>
<translation>&amp;Network</translation>
</message>
@@ -1403,7 +1355,7 @@ Address: %4
<translation>Map port using &amp;UPnP</translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+29"/>
<source>Proxy &amp;IP:</source>
<translation>Proxy &amp;IP:</translation>
</message>
@@ -1418,16 +1370,6 @@ Address: %4
<translation>Port of the proxy (e.g. 9050)</translation>
</message>
<message>
- <location line="+7"/>
- <source>SOCKS &amp;Version:</source>
- <translation>SOCKS &amp;Version:</translation>
- </message>
- <message>
- <location line="+13"/>
- <source>SOCKS version of the proxy (e.g. 5)</source>
- <translation>SOCKS version of the proxy (e.g. 5)</translation>
- </message>
- <message>
<location line="+36"/>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
@@ -1478,22 +1420,12 @@ Address: %4
<translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation>
</message>
<message>
- <location line="+9"/>
- <source>Whether to show Bitcoin addresses in the transaction list or not.</source>
- <translation>Whether to show Bitcoin addresses in the transaction list or not.</translation>
- </message>
- <message>
- <location line="+3"/>
- <source>&amp;Display addresses in transaction list</source>
- <translation>&amp;Display addresses in transaction list</translation>
- </message>
- <message>
- <location line="-262"/>
+ <location line="-240"/>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+422"/>
+ <location line="+402"/>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1503,12 +1435,12 @@ Address: %4
<translation>&amp;Cancel</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+72"/>
+ <location filename="../optionsdialog.cpp" line="+68"/>
<source>default</source>
<translation>default</translation>
</message>
<message>
- <location line="+61"/>
+ <location line="+63"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
@@ -1547,18 +1479,23 @@ Address: %4
<translation>Form</translation>
</message>
<message>
- <location line="+50"/>
- <location line="+231"/>
+ <location line="+52"/>
+ <location line="+394"/>
<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>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.</translation>
</message>
<message>
- <location line="-238"/>
+ <location line="-401"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+33"/>
+ <source>Watch-only:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+43"/>
<source>Available:</source>
<translation type="unfinished"></translation>
</message>
@@ -1583,12 +1520,12 @@ Address: %4
<translation>Immature:</translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+16"/>
<source>Mined balance that has not yet matured</source>
<translation>Mined balance that has not yet matured</translation>
</message>
<message>
- <location line="+16"/>
+ <location line="+23"/>
<source>Total:</source>
<translation>Total:</translation>
</message>
@@ -1598,12 +1535,32 @@ Address: %4
<translation>Your current total balance</translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+38"/>
+ <source>Your current balance in watch-only addresses</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+44"/>
+ <source>Current total balance in watch-only addresses</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+67"/>
<source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
<translation>&lt;b&gt;Recent transactions&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../overviewpage.cpp" line="+120"/>
+ <location filename="../overviewpage.cpp" line="+123"/>
<location line="+1"/>
<source>out of sync</source>
<translation>out of sync</translation>
@@ -1612,68 +1569,86 @@ Address: %4
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+403"/>
- <location line="+13"/>
+ <location filename="../paymentserver.cpp" line="+405"/>
+ <location line="+14"/>
+ <location line="+7"/>
<source>URI handling</source>
<translation type="unfinished">URI handling</translation>
</message>
<message>
- <location line="+1"/>
- <source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation type="unfinished">URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
+ <location line="-7"/>
+ <source>Invalid payment address %1</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+96"/>
- <source>Requested payment amount of %1 is too small (considered dust).</source>
+ <location line="+84"/>
+ <location line="+9"/>
+ <location line="+32"/>
+ <source>Payment request rejected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-221"/>
- <location line="+212"/>
- <location line="+13"/>
- <location line="+95"/>
- <location line="+18"/>
- <location line="+16"/>
- <source>Payment request error</source>
+ <location line="-41"/>
+ <source>Payment request network doesn&apos;t match client network.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-353"/>
- <source>Cannot start bitcoin: click-to-pay handler</source>
+ <location line="+9"/>
+ <source>Payment request has expired.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+58"/>
- <source>Net manager warning</source>
+ <location line="+7"/>
+ <source>Payment request is not initialized.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <source>Your active proxy doesn&apos;t support SOCKS5, which is required for payment requests via proxy.</source>
+ <location line="+34"/>
+ <source>Requested payment amount of %1 is too small (considered dust).</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+52"/>
+ <location line="-253"/>
+ <location line="+219"/>
+ <location line="+34"/>
+ <location line="+98"/>
+ <location line="+14"/>
+ <location line="+18"/>
+ <source>Payment request error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-382"/>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+105"/>
<source>Payment request fetch URL is invalid: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+27"/>
+ <location line="+21"/>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
<source>Payment request file handling</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
- <source>Payment request file can not be read or processed! This can be caused by an invalid payment request file.</source>
+ <source>Payment request file cannot be read! This can be caused by an invalid payment request file.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+73"/>
+ <location line="+104"/>
<source>Unverified payment requests to custom payment scripts are unsupported.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+59"/>
+ <location line="+58"/>
<source>Refund from %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1683,12 +1658,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+24"/>
- <source>Payment request can not be parsed or processed!</source>
+ <location line="+20"/>
+ <source>Payment request cannot be parsed!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+13"/>
<source>Bad response from server %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1704,38 +1679,79 @@ Address: %4
</message>
</context>
<context>
+ <name>PeerTableModel</name>
+ <message>
+ <location filename="../peertablemodel.cpp" line="+112"/>
+ <source>User Agent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Address/Hostname</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Ping Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../bitcoin.cpp" line="+71"/>
- <location line="+7"/>
- <location line="+13"/>
- <source>Bitcoin</source>
- <translation>Bitcoin</translation>
+ <location filename="../bitcoinunits.cpp" line="+200"/>
+ <source>Amount</source>
+ <translation type="unfinished">Amount</translation>
</message>
<message>
- <location line="-19"/>
- <source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
- <translation>Error: Specified data directory &quot;%1&quot; does not exist.</translation>
+ <location filename="../guiutil.cpp" line="+97"/>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
- <source>Error: Cannot parse configuration file: %1. Only use key=value syntax.</source>
+ <location line="+673"/>
+ <source>%1 d</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
- <source>Error: Invalid combination of -regtest and -testnet.</source>
+ <location line="+2"/>
+ <source>%1 h</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>%1 m</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>%1 s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+17"/>
+ <source>NETWORK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>UNKNOWN</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+60"/>
- <source>Bitcoin Core didn&apos;t yet exit safely...</source>
+ <location line="+8"/>
+ <source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+89"/>
- <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation type="unfinished">Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
+ <location line="+5"/>
+ <source>N/A</source>
+ <translation type="unfinished">N/A</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>%1 ms</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1751,7 +1767,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+28"/>
+ <location line="+32"/>
<source>Save QR Code</source>
<translation type="unfinished">Save QR Code</translation>
</message>
@@ -1772,19 +1788,32 @@ Address: %4
<location line="+10"/>
<location line="+23"/>
<location line="+26"/>
+ <location line="+26"/>
<location line="+23"/>
<location line="+23"/>
<location line="+36"/>
<location line="+23"/>
<location line="+36"/>
<location line="+23"/>
+ <location line="+462"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
+ <location line="+23"/>
<location line="+23"/>
- <location filename="../rpcconsole.cpp" line="+373"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
- <location line="-223"/>
+ <location line="-987"/>
<source>Client version</source>
<translation>Client version</translation>
</message>
@@ -1809,6 +1838,11 @@ Address: %4
<translation>Using OpenSSL version</translation>
</message>
<message>
+ <location line="+26"/>
+ <source>Using BerkeleyDB version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+49"/>
<source>Startup time</source>
<translation>Startup time</translation>
@@ -1839,12 +1873,99 @@ Address: %4
<translation>Current number of blocks</translation>
</message>
<message>
+ <location line="+300"/>
+ <source>Received</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+80"/>
+ <source>Sent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+41"/>
+ <source>&amp;Peers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+39"/>
+ <location filename="../rpcconsole.cpp" line="+234"/>
+ <location line="+327"/>
+ <source>Select a peer to view detailed information.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+25"/>
+ <source>Direction</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Version</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>User Agent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Services</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Sync Node</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Starting Height</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Sync Height</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Ban Score</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Connection Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Last Send</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Last Receive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Bytes Sent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+23"/>
- <source>Estimated total blocks</source>
- <translation>Estimated total blocks</translation>
+ <source>Bytes Received</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+23"/>
+ <source>Ping Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-761"/>
<source>Last block time</source>
<translation>Last block time</translation>
</message>
@@ -1874,24 +1995,22 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+64"/>
- <location filename="../rpcconsole.cpp" line="-10"/>
+ <location filename="../rpcconsole.cpp" line="-165"/>
<source>In:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+80"/>
- <location filename="../rpcconsole.cpp" line="+1"/>
+ <location line="+1"/>
<source>Out:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-521"/>
+ <location filename="../forms/rpcconsole.ui" line="-354"/>
<source>Build date</source>
<translation>Build date</translation>
</message>
<message>
- <location line="+206"/>
+ <location line="+183"/>
<source>Debug log file</source>
<translation>Debug log file</translation>
</message>
@@ -1921,7 +2040,7 @@ Address: %4
<translation>Type &lt;b&gt;help&lt;/b&gt; for an overview of available commands.</translation>
</message>
<message>
- <location line="+136"/>
+ <location line="+134"/>
<source>%1 B</source>
<translation type="unfinished"></translation>
</message>
@@ -1941,18 +2060,45 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+95"/>
+ <source>via %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <location line="+1"/>
+ <source>never</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+7"/>
- <source>%1 m</source>
+ <source>Inbound</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
- <source>%1 h</source>
+ <location line="+0"/>
+ <source>Outbound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Yes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>No</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
- <source>%1 h %2 m</source>
+ <location line="+1"/>
+ <source>Fetching...</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2085,7 +2231,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../receiverequestdialog.cpp" line="+56"/>
+ <location filename="../receiverequestdialog.cpp" line="+65"/>
<source>Request payment to %1</source>
<translation type="unfinished"></translation>
</message>
@@ -2148,12 +2294,12 @@ Address: %4
<translation type="unfinished">Message</translation>
</message>
<message>
- <location line="+0"/>
+ <location line="+99"/>
<source>Amount</source>
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location line="+38"/>
+ <location line="-59"/>
<source>(no label)</source>
<translation type="unfinished">(no label)</translation>
</message>
@@ -2172,8 +2318,7 @@ Address: %4
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+380"/>
- <location line="+80"/>
+ <location filename="../sendcoinsdialog.cpp" line="+447"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -2223,12 +2368,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+32"/>
- <source>Low Output:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+48"/>
+ <location line="+80"/>
<source>After Fee:</source>
<translation type="unfinished"></translation>
</message>
@@ -2263,7 +2403,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="-271"/>
+ <source>Dust:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+274"/>
<source>Clear &amp;All</source>
<translation>Clear &amp;All</translation>
</message>
@@ -2283,7 +2428,7 @@ Address: %4
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-229"/>
+ <location filename="../sendcoinsdialog.cpp" line="-215"/>
<source>Confirm send coins</source>
<translation>Confirm send coins</translation>
</message>
@@ -2296,7 +2441,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-121"/>
+ <location line="-122"/>
<source>Copy quantity</source>
<translation type="unfinished"></translation>
</message>
@@ -2326,17 +2471,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <source>Copy low output</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Copy change</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+170"/>
+ <location line="+171"/>
<source>Total Amount %1 (= %2)</source>
<translation type="unfinished"></translation>
</message>
@@ -2346,7 +2486,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+203"/>
+ <location line="+189"/>
<source>The recipient address is not valid, please recheck.</source>
<translation>The recipient address is not valid, please recheck.</translation>
</message>
@@ -2396,23 +2536,18 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-367"/>
- <source>Are you sure you want to send?</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+9"/>
- <source>added as transaction fee</source>
+ <location line="-504"/>
+ <source>Copy dust</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+171"/>
- <source>Payment request expired</source>
+ <location line="+151"/>
+ <source>Are you sure you want to send?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
- <source>Invalid payment address %1</source>
+ <location line="+9"/>
+ <source>added as transaction fee</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -2431,17 +2566,12 @@ Address: %4
<translation>Pay &amp;To:</translation>
</message>
<message>
- <location line="+18"/>
- <source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
- </message>
- <message>
<location filename="../sendcoinsentry.cpp" line="+30"/>
<source>Enter a label for this address to add it to your address book</source>
<translation>Enter a label for this address to add it to your address book</translation>
</message>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="+57"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+75"/>
<source>&amp;Label:</source>
<translation>&amp;Label:</translation>
</message>
@@ -2456,7 +2586,12 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+50"/>
+ <location line="+33"/>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+17"/>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -2518,7 +2653,7 @@ Address: %4
<context>
<name>ShutdownWindow</name>
<message>
- <location filename="../utilitydialog.cpp" line="+52"/>
+ <location filename="../utilitydialog.cpp" line="+51"/>
<source>Bitcoin Core is shutting down...</source>
<translation type="unfinished"></translation>
</message>
@@ -2547,8 +2682,8 @@ Address: %4
</message>
<message>
<location line="+18"/>
- <source>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+7"/>
@@ -2620,8 +2755,8 @@ Address: %4
</message>
<message>
<location line="+21"/>
- <source>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation>The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+37"/>
@@ -2639,17 +2774,12 @@ Address: %4
<translation>Reset all verify message fields</translation>
</message>
<message>
- <location filename="../signverifymessagedialog.cpp" line="+30"/>
- <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
- <translation>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
- </message>
- <message>
- <location line="-1"/>
+ <location filename="../signverifymessagedialog.cpp" line="+29"/>
<source>Click &quot;Sign Message&quot; to generate signature</source>
<translation>Click &quot;Sign Message&quot; to generate signature</translation>
</message>
<message>
- <location line="+84"/>
+ <location line="+83"/>
<location line="+80"/>
<source>The entered address is invalid.</source>
<translation>The entered address is invalid.</translation>
@@ -2744,7 +2874,7 @@ Address: %4
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+29"/>
+ <location filename="../transactiondesc.cpp" line="+33"/>
<source>Open until %1</source>
<translation>Open until %1</translation>
</message>
@@ -2798,39 +2928,45 @@ Address: %4
</message>
<message>
<location line="+5"/>
- <location line="+17"/>
+ <location line="+13"/>
+ <location line="+72"/>
<source>From</source>
<translation>From</translation>
</message>
<message>
- <location line="+1"/>
- <location line="+22"/>
- <location line="+58"/>
+ <location line="-71"/>
+ <location line="+20"/>
+ <location line="+69"/>
<source>To</source>
<translation>To</translation>
</message>
<message>
- <location line="-77"/>
- <location line="+2"/>
+ <location line="-87"/>
<source>own address</source>
<translation>own address</translation>
</message>
<message>
- <location line="-2"/>
+ <location line="+0"/>
+ <location line="+69"/>
+ <source>watch-only</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-67"/>
<source>label</source>
<translation>label</translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+34"/>
<location line="+12"/>
- <location line="+45"/>
- <location line="+17"/>
+ <location line="+53"/>
+ <location line="+26"/>
<location line="+53"/>
<source>Credit</source>
<translation>Credit</translation>
</message>
<message numerus="yes">
- <location line="-125"/>
+ <location line="-142"/>
<source>matures in %n more block(s)</source>
<translation>
<numerusform>matures in %n more block</numerusform>
@@ -2843,15 +2979,24 @@ Address: %4
<translation>not accepted</translation>
</message>
<message>
- <location line="+44"/>
- <location line="+8"/>
- <location line="+15"/>
+ <location line="+59"/>
+ <location line="+25"/>
<location line="+53"/>
<source>Debit</source>
<translation>Debit</translation>
</message>
<message>
- <location line="-62"/>
+ <location line="-68"/>
+ <source>Total debit</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Total credit</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
<source>Transaction fee</source>
<translation>Transaction fee</translation>
</message>
@@ -2908,16 +3053,18 @@ Address: %4
</message>
<message>
<location line="+1"/>
+ <location line="+1"/>
<source>true</source>
<translation>true</translation>
</message>
<message>
- <location line="+0"/>
+ <location line="-1"/>
+ <location line="+1"/>
<source>false</source>
<translation>false</translation>
</message>
<message>
- <location line="-230"/>
+ <location line="-242"/>
<source>, has not been successfully broadcast yet</source>
<translation>, has not been successfully broadcast yet</translation>
</message>
@@ -2930,7 +3077,7 @@ Address: %4
</translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+67"/>
<source>unknown</source>
<translation>unknown</translation>
</message>
@@ -2951,7 +3098,7 @@ Address: %4
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+238"/>
+ <location filename="../transactiontablemodel.cpp" line="+237"/>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -2966,12 +3113,7 @@ Address: %4
<translation>Address</translation>
</message>
<message>
- <location line="+0"/>
- <source>Amount</source>
- <translation>Amount</translation>
- </message>
- <message>
- <location line="+70"/>
+ <location line="+76"/>
<source>Immature (%1 confirmations, will be available after %2)</source>
<translation type="unfinished"></translation>
</message>
@@ -3049,12 +3191,12 @@ Address: %4
<translation>Mined</translation>
</message>
<message>
- <location line="+38"/>
+ <location line="+41"/>
<source>(n/a)</source>
<translation>(n/a)</translation>
</message>
<message>
- <location line="+192"/>
+ <location line="+193"/>
<source>Transaction status. Hover over this field to show number of confirmations.</source>
<translation>Transaction status. Hover over this field to show number of confirmations.</translation>
</message>
@@ -3153,7 +3295,7 @@ Address: %4
<translation>Min amount</translation>
</message>
<message>
- <location line="+34"/>
+ <location line="+36"/>
<source>Copy address</source>
<translation>Copy address</translation>
</message>
@@ -3238,12 +3380,7 @@ Address: %4
<translation>Address</translation>
</message>
<message>
- <location line="+1"/>
- <source>Amount</source>
- <translation>Amount</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+2"/>
<source>ID</source>
<translation>ID</translation>
</message>
@@ -3259,6 +3396,14 @@ Address: %4
</message>
</context>
<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <location filename="../bitcoingui.cpp" line="+101"/>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>WalletFrame</name>
<message>
<location filename="../walletframe.cpp" line="+26"/>
@@ -3269,7 +3414,7 @@ Address: %4
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+258"/>
+ <location filename="../walletmodel.cpp" line="+280"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -3320,27 +3465,12 @@ Address: %4
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+262"/>
- <source>Usage:</source>
- <translation>Usage:</translation>
- </message>
- <message>
- <location line="-66"/>
- <source>List commands</source>
- <translation>List commands</translation>
- </message>
- <message>
- <location line="-15"/>
- <source>Get help for a command</source>
- <translation>Get help for a command</translation>
- </message>
- <message>
- <location line="+28"/>
+ <location filename="../bitcoinstrings.cpp" line="+249"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
<message>
- <location line="+32"/>
+ <location line="+28"/>
<source>Specify configuration file (default: bitcoin.conf)</source>
<translation>Specify configuration file (default: bitcoin.conf)</translation>
</message>
@@ -3355,7 +3485,7 @@ Address: %4
<translation>Specify data directory</translation>
</message>
<message>
- <location line="-46"/>
+ <location line="-44"/>
<source>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</source>
<translation>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</translation>
</message>
@@ -3365,62 +3495,52 @@ Address: %4
<translation>Maintain at most &lt;n&gt; connections to peers (default: 125)</translation>
</message>
<message>
- <location line="-58"/>
+ <location line="-62"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
<message>
- <location line="+101"/>
+ <location line="+103"/>
<source>Specify your own public address</source>
<translation>Specify your own public address</translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+7"/>
<source>Threshold for disconnecting misbehaving peers (default: 100)</source>
<translation>Threshold for disconnecting misbehaving peers (default: 100)</translation>
</message>
<message>
- <location line="-173"/>
+ <location line="-181"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation>
</message>
<message>
- <location line="-52"/>
- <source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
- <translation>An error occurred while setting up the RPC port %u for listening on IPv4: %s</translation>
- </message>
- <message>
- <location line="+50"/>
+ <location line="-2"/>
<source>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
<translation>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+59"/>
<source>Accept command line and JSON-RPC commands</source>
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="+7"/>
- <source>Bitcoin Core RPC client version</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+88"/>
+ <location line="+99"/>
<source>Run in the background as a daemon and accept commands</source>
<translation>Run in the background as a daemon and accept commands</translation>
</message>
<message>
- <location line="+43"/>
+ <location line="+36"/>
<source>Use the test network</source>
<translation>Use the test network</translation>
</message>
<message>
- <location line="-137"/>
+ <location line="-134"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
<message>
- <location line="-117"/>
+ <location line="-154"/>
<source>%s, you must set a rpcpassword in the configuration file:
%s
It is recommended you use the following random password:
@@ -3445,42 +3565,32 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+15"/>
<source>Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
- <source>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</source>
- <translation>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+10"/>
<source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
<translation>Bind to given address and always listen on it. Use [host]:port notation for IPv6</translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+13"/>
<source>Continuously rate-limit free transactions to &lt;n&gt;*1000 bytes per minute (default:15)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>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.</source>
- <translation>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.</translation>
- </message>
- <message>
- <location line="+4"/>
- <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source>
+ <location line="+6"/>
+ <source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Error: Listening for incoming connections failed (listen returned error %d)</source>
+ <location line="+6"/>
+ <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <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>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.</translation>
</message>
@@ -3490,17 +3600,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!</translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+12"/>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
<translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
</message>
<message>
- <location line="+6"/>
- <source>Fees smaller than this are considered zero fee (for transaction creation) (default:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+12"/>
<source>Flush database activity from memory pool to disk log every &lt;n&gt; megabytes (default: 100)</source>
<translation type="unfinished"></translation>
</message>
@@ -3510,12 +3615,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+5"/>
<source>In this mode -genproclimit controls how many blocks are generated immediately.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+15"/>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation type="unfinished"></translation>
</message>
@@ -3530,7 +3635,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+7"/>
<source>Unable to bind to %s on this computer. Bitcoin Core is probably already running.</source>
<translation type="unfinished"></translation>
</message>
@@ -3545,12 +3650,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</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>Warning: Please check that your computer&apos;s date and time are correct! If your clock is wrong Bitcoin will not work properly.</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation>
</message>
@@ -3570,7 +3670,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>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.</translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+10"/>
<source>(default: 1)</source>
<translation type="unfinished"></translation>
</message>
@@ -3591,46 +3691,26 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<location line="+1"/>
- <source>Bitcoin Core Daemon</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
<source>Block creation options:</source>
<translation>Block creation options:</translation>
</message>
<message>
- <location line="+5"/>
- <source>Clear list of wallet transactions (diagnostic tool; implies -rescan)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+6"/>
<source>Connect only to the specified node(s)</source>
<translation>Connect only to the specified node(s)</translation>
</message>
<message>
- <location line="+1"/>
- <source>Connect through SOCKS proxy</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Connect to JSON-RPC on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+3"/>
<source>Connection options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Corrupted block database detected</source>
<translation>Corrupted block database detected</translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Debugging/Testing options:</source>
<translation type="unfinished"></translation>
</message>
@@ -3680,7 +3760,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Error: Disk space is low!</translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Error: Wallet locked, unable to create transaction!</source>
<translation>Error: Wallet locked, unable to create transaction!</translation>
</message>
@@ -3745,22 +3825,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Failed to write undo data</translation>
</message>
<message>
- <location line="+1"/>
- <source>Fee per kB to add to transactions you send</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Fees smaller than this are considered zero fee (for relaying) (default:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Find peers using DNS lookup (default: 1 unless -connect)</source>
- <translation>Find peers using DNS lookup (default: 1 unless -connect)</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Force safe mode (default: 0)</source>
<translation type="unfinished"></translation>
</message>
@@ -3770,7 +3835,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Generate coins (default: 0)</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>How many blocks to check at startup (default: 288, 0 = all)</source>
<translation>How many blocks to check at startup (default: 288, 0 = all)</translation>
</message>
@@ -3785,17 +3850,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+3"/>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
<translation>Incorrect or no genesis block found. Wrong datadir for network?</translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+4"/>
<source>Invalid -onion address: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+21"/>
<source>Not enough file descriptors available.</source>
<translation>Not enough file descriptors available.</translation>
</message>
@@ -3805,22 +3870,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <source>RPC client options:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+4"/>
+ <location line="+7"/>
<source>Rebuild block chain index from current blk000??.dat files</source>
<translation>Rebuild block chain index from current blk000??.dat files</translation>
</message>
<message>
- <location line="+6"/>
- <source>Select SOCKS version for -proxy (4 or 5, default: 5)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+6"/>
+ <location line="+10"/>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation type="unfinished"></translation>
</message>
@@ -3835,7 +3890,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Set the number of threads to service RPC calls (default: 4)</translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+9"/>
<source>Specify wallet file (within data directory)</source>
<translation>Specify wallet file (within data directory)</translation>
</message>
@@ -3845,17 +3900,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <source>This is intended for regression testing tools and app development.</source>
+ <location line="+1"/>
+ <source>Stop running after importing blocks from disk (default: 0)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
- <source>Usage (deprecated, use bitcoin-cli):</source>
+ <location line="+4"/>
+ <source>This is intended for regression testing tools and app development.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+14"/>
<source>Verifying blocks...</source>
<translation>Verifying blocks...</translation>
</message>
@@ -3866,11 +3921,6 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<location line="+1"/>
- <source>Wait for RPC server to start</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Wallet %s resides outside data directory %s</source>
<translation>Wallet %s resides outside data directory %s</translation>
</message>
@@ -3880,12 +3930,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>Warning: Deprecated argument -debugnet ignored, use -debug=net</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+5"/>
<source>You need to rebuild the database using -reindex to change -txindex</source>
<translation>You need to rebuild the database using -reindex to change -txindex</translation>
</message>
@@ -3895,31 +3940,171 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Imports blocks from external blk000??.dat file</translation>
</message>
<message>
- <location line="-150"/>
+ <location line="-195"/>
+ <source>(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>An error occurred while setting up the RPC address %s port %u for listening: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+22"/>
+ <location line="+6"/>
+ <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>Error: Unsupported argument -socks found. Setting SOCKS version isn&apos;t possible anymore, only SOCKS5 proxies are supported.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
<translation>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+9"/>
+ <source>Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+11"/>
<source>Output debugging information (default: 0, supplying &lt;category&gt; is optional)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
+ <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+103"/>
+ <location line="+11"/>
+ <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit &lt;https://www.openssl.org/&gt; and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Warning: Please check that your computer&apos;s date and time are correct! If your clock is wrong Bitcoin Core will not work properly.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>Whitelist peers connecting from the given netmask or ip. Can be specified multiple times.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Always query for peer addresses via DNS lookup (default: 0)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Cannot resolve -whitebind address: &apos;%s&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Connect through SOCKS5 proxy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Copyright (C) 2009-%i The Bitcoin Core Developers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Could not parse -rpcbind value %s as network address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Error loading wallet.dat: Wallet requires newer version of Bitcoin Core</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Error: Unsupported argument -tor found, use -onion.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>Fee (in BTC/kB) to add to transactions you send (default: %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>Include IP addresses in debug output (default: 0)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Information</source>
<translation>Information</translation>
</message>
<message>
+ <location line="+1"/>
+ <source>Initialization sanity check failed. Bitcoin Core is shutting down.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+4"/>
<source>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation>Invalid amount for -minrelaytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
@@ -3930,12 +4115,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Invalid amount for -mintxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
+ <location line="+1"/>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+3"/>
+ <source>Invalid netmask specified in -whitelist: &apos;%s&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Keep at most &lt;n&gt; unconnectable blocks in memory (default: %u)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Limit size of signature cache to &lt;n&gt; entries (default: 50000)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>Log transaction priority and fee per kB when mining blocks (default: 0)</source>
<translation type="unfinished"></translation>
</message>
@@ -3955,6 +4155,16 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Maximum per-connection send buffer, &lt;n&gt;*1000 bytes (default: 1000)</translation>
</message>
<message>
+ <location line="+1"/>
+ <source>Need to specify a port with -whitebind: &apos;%s&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Node relay options:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+2"/>
<source>Only accept block chain matching built-in checkpoints (default: 1)</source>
<translation>Only accept block chain matching built-in checkpoints (default: 1)</translation>
@@ -3980,7 +4190,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>RPC server options:</source>
<translation type="unfinished"></translation>
</message>
@@ -3995,18 +4205,18 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <source>Run a thread to flush wallet periodically (default: 1)</source>
+ <location line="+2"/>
+ <source>Relay and mine data carrier transactions (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
- <translation>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</translation>
+ <location line="+1"/>
+ <source>Relay non-P2SH multisig (default: 1)</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>Send command to Bitcoin Core</source>
+ <location line="+3"/>
+ <source>Run a thread to flush wallet periodically (default: 1)</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -4031,11 +4241,6 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<location line="+1"/>
- <source>Show benchmark information (default: 0)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Shrink debug.log file on client startup (default: 1 when no -debug)</source>
<translation>Shrink debug.log file on client startup (default: 1 when no -debug)</translation>
</message>
@@ -4050,17 +4255,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Specify connection timeout in milliseconds (default: 5000)</translation>
</message>
<message>
- <location line="+6"/>
- <source>Start Bitcoin Core Daemon</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+7"/>
<source>System error: </source>
<translation>System error: </translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+2"/>
+ <source>This is experimental software.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Transaction amount too small</source>
<translation>Transaction amount too small</translation>
</message>
@@ -4075,7 +4280,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Transaction too large</translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+1"/>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Use UPnP to map the listening port (default: 0)</source>
<translation>Use UPnP to map the listening port (default: 0)</translation>
</message>
@@ -4090,29 +4300,39 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Username for JSON-RPC connections</translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+4"/>
+ <source>Wallet needed to be rewritten: restart Bitcoin Core to complete</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Warning</source>
<translation>Warning</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>Warning: This version is obsolete, upgrade required!</source>
<translation>Warning: This version is obsolete, upgrade required!</translation>
</message>
<message>
- <location line="+2"/>
- <source>Zapping all transactions from wallet...</source>
+ <location line="+1"/>
+ <source>Warning: Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
- <source>on startup</source>
+ <source>Warning: Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Zapping all transactions from wallet...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
- <source>version</source>
- <translation type="unfinished">version</translation>
+ <source>on startup</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
@@ -4120,47 +4340,37 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>wallet.dat corrupt, salvage failed</translation>
</message>
<message>
- <location line="-71"/>
+ <location line="-64"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-78"/>
- <source>Allow JSON-RPC connections from specified IP address</source>
- <translation>Allow JSON-RPC connections from specified IP address</translation>
- </message>
- <message>
- <location line="+95"/>
- <source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
- <translation>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</translation>
- </message>
- <message>
<location line="-164"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+197"/>
+ <location line="+210"/>
<source>Upgrade wallet to latest format</source>
<translation>Upgrade wallet to latest format</translation>
</message>
<message>
- <location line="-28"/>
+ <location line="-27"/>
<source>Set key pool size to &lt;n&gt; (default: 100)</source>
<translation>Set key pool size to &lt;n&gt; (default: 100)</translation>
</message>
<message>
- <location line="-12"/>
+ <location line="-8"/>
<source>Rescan the block chain for missing wallet transactions</source>
<translation>Rescan the block chain for missing wallet transactions</translation>
</message>
<message>
- <location line="+43"/>
+ <location line="+36"/>
<source>Use OpenSSL (https) for JSON-RPC connections</source>
<translation>Use OpenSSL (https) for JSON-RPC connections</translation>
</message>
<message>
- <location line="-34"/>
+ <location line="-31"/>
<source>Server certificate file (default: server.cert)</source>
<translation>Server certificate file (default: server.cert)</translation>
</message>
@@ -4170,42 +4380,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Server private key (default: server.pem)</translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+19"/>
<source>This help message</source>
<translation>This help message</translation>
</message>
<message>
- <location line="+7"/>
- <source>Unable to bind to %s on this computer (bind returned error %d, %s)</source>
- <translation>Unable to bind to %s on this computer (bind returned error %d, %s)</translation>
- </message>
- <message>
- <location line="-126"/>
+ <location line="-118"/>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
<message>
- <location line="+67"/>
+ <location line="+68"/>
<source>Loading addresses...</source>
<translation>Loading addresses...</translation>
</message>
<message>
- <location line="-40"/>
+ <location line="-42"/>
<source>Error loading wallet.dat: Wallet corrupted</source>
<translation>Error loading wallet.dat: Wallet corrupted</translation>
</message>
<message>
- <location line="+1"/>
- <source>Error loading wallet.dat: Wallet requires newer version of Bitcoin</source>
- <translation>Error loading wallet.dat: Wallet requires newer version of Bitcoin</translation>
- </message>
- <message>
- <location line="+113"/>
- <source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
- <translation>Wallet needed to be rewritten: restart Bitcoin to complete</translation>
- </message>
- <message>
- <location line="-115"/>
+ <location line="-1"/>
<source>Error loading wallet.dat</source>
<translation>Error loading wallet.dat</translation>
</message>
@@ -4220,12 +4415,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-1"/>
- <source>Unknown -socks proxy version requested: %i</source>
- <translation>Unknown -socks proxy version requested: %i</translation>
- </message>
- <message>
- <location line="-120"/>
+ <location line="-122"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
<translation>Cannot resolve -bind address: &apos;%s&apos;</translation>
</message>
@@ -4235,7 +4425,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Cannot resolve -externalip address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+54"/>
+ <location line="+56"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
@@ -4245,63 +4435,54 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Invalid amount</translation>
</message>
<message>
- <location line="-6"/>
+ <location line="-7"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+13"/>
<source>Loading block index...</source>
<translation>Loading block index...</translation>
</message>
<message>
- <location line="-69"/>
+ <location line="-70"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation>Add a node to connect to and attempt to keep the connection open</translation>
</message>
<message>
- <location line="+70"/>
+ <location line="+71"/>
<source>Loading wallet...</source>
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-63"/>
+ <location line="-66"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+4"/>
<source>Cannot write default address</source>
<translation>Cannot write default address</translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+86"/>
<source>Rescanning...</source>
<translation>Rescanning...</translation>
</message>
<message>
- <location line="-68"/>
+ <location line="-73"/>
<source>Done loading</source>
<translation>Done loading</translation>
</message>
<message>
- <location line="+100"/>
+ <location line="+101"/>
<source>To use the %s option</source>
<translation>To use the %s option</translation>
</message>
<message>
- <location line="-92"/>
+ <location line="-93"/>
<source>Error</source>
<translation>Error</translation>
</message>
- <message>
- <location line="-41"/>
- <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>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.</translation>
- </message>
</context>
</TS>
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index 74fb64ace3..a2ff148d9d 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -6,7 +6,7 @@
#include <QImageWriter>
#include <QMenu>
-#include <QTemporaryFile>
+#include <QBuffer>
#include <QWidget>
#undef slots
@@ -95,14 +95,14 @@ void MacDockIconHandler::setIcon(const QIcon &icon)
QSize size = icon.actualSize(QSize(128, 128));
QPixmap pixmap = icon.pixmap(size);
- // write temp file hack (could also be done through QIODevice [memory])
- QTemporaryFile notificationIconFile;
- if (!pixmap.isNull() && notificationIconFile.open()) {
- QImageWriter writer(&notificationIconFile, "PNG");
+ // Write image into a R/W buffer from raw pixmap, then save the image.
+ QBuffer notificationBuffer;
+ if (!pixmap.isNull() && notificationBuffer.open(QIODevice::ReadWrite)) {
+ QImageWriter writer(&notificationBuffer, "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];
+ NSData* macImgData = [NSData dataWithBytes:notificationBuffer.buffer().data()
+ length:notificationBuffer.buffer().size()];
+ image = [[NSImage alloc] initWithData:macImgData];
}
}
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 597be40abd..fd1d446f9b 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -15,11 +15,11 @@
#include "optionsmodel.h"
#include "main.h" // for MAX_SCRIPTCHECK_THREADS
+#include "netbase.h"
+#include "txdb.h" // for -dbcache defaults
#ifdef ENABLE_WALLET
#include "wallet.h" // for CWallet::minTxFee
#endif
-#include "netbase.h"
-#include "txdb.h" // for -dbcache defaults
#include <QDir>
#include <QIntValidator>
@@ -185,7 +185,6 @@ void OptionsDialog::setMapper()
/* Display */
mapper->addMapping(ui->lang, OptionsModel::Language);
mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
- mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index f07e66bf04..99928ebe4d 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -59,10 +59,6 @@ void OptionsModel::Init()
settings.setValue("nDisplayUnit", BitcoinUnits::BTC);
nDisplayUnit = settings.value("nDisplayUnit").toInt();
- if (!settings.contains("bDisplayAddresses"))
- settings.setValue("bDisplayAddresses", false);
- bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool();
-
if (!settings.contains("strThirdPartyTxUrls"))
settings.setValue("strThirdPartyTxUrls", "");
strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
@@ -200,8 +196,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
#endif
case DisplayUnit:
return nDisplayUnit;
- case DisplayAddresses:
- return bDisplayAddresses;
case ThirdPartyTxUrls:
return strThirdPartyTxUrls;
case Language:
@@ -296,10 +290,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
case DisplayUnit:
setDisplayUnit(value);
break;
- case DisplayAddresses:
- bDisplayAddresses = value.toBool();
- settings.setValue("bDisplayAddresses", bDisplayAddresses);
- break;
case ThirdPartyTxUrls:
if (strThirdPartyTxUrls != value.toString()) {
strThirdPartyTxUrls = value.toString();
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 89c2ec7453..80adab89c8 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -32,10 +32,8 @@ public:
ProxyUse, // bool
ProxyIP, // QString
ProxyPort, // int
- ProxySocksVersion, // int
Fee, // qint64
DisplayUnit, // BitcoinUnits::Unit
- DisplayAddresses, // bool
ThirdPartyTxUrls, // QString
Language, // QString
CoinControlFeatures, // bool
@@ -59,7 +57,6 @@ public:
bool getMinimizeToTray() { return fMinimizeToTray; }
bool getMinimizeOnClose() { return fMinimizeOnClose; }
int getDisplayUnit() { return nDisplayUnit; }
- bool getDisplayAddresses() { return bDisplayAddresses; }
QString getThirdPartyTxUrls() { return strThirdPartyTxUrls; }
bool getProxySettings(QNetworkProxy& proxy) const;
bool getCoinControlFeatures() { return fCoinControlFeatures; }
@@ -75,7 +72,6 @@ private:
bool fMinimizeOnClose;
QString language;
int nDisplayUnit;
- bool bDisplayAddresses;
QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
/* settings that were overriden by command-line */
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 1278f368cf..b5a3de48ca 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -72,7 +72,7 @@ public:
foreground = option.palette.color(QPalette::Text);
}
painter->setPen(foreground);
- QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true);
+ QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::separatorAlways);
if(!confirmed)
{
amountText = QString("[") + amountText + QString("]");
@@ -147,14 +147,14 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64
currentWatchOnlyBalance = watchOnlyBalance;
currentWatchUnconfBalance = watchUnconfBalance;
currentWatchImmatureBalance = watchImmatureBalance;
- 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));
- ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance));
- ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance));
- ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance));
- ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance));
+ ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways));
+ ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance, false, BitcoinUnits::separatorAlways));
+ ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance, false, BitcoinUnits::separatorAlways));
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
// for the non-mining users
@@ -162,15 +162,16 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64
bool showWatchOnlyImmature = watchImmatureBalance != 0;
bool showWatchOnly = (watchOnlyBalance != 0 || watchUnconfBalance != 0 || showWatchOnlyImmature);
- // for symmetry reasons also show immature label when the watchonly one is shown
+ // for symmetry reasons also show immature label when the watch-only one is shown
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
- ui->labelWatchonly->setVisible(showWatchOnly); // show Watchonly label
- ui->lineWatchBalance->setVisible(showWatchOnly); // show watchonly balance separator line
- ui->labelWatchAvailable->setVisible(showWatchOnly); // show watchonly available balance
- ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watchonly immature balance
- ui->labelWatchPending->setVisible(showWatchOnly); // show watchonly pending balance
- ui->labelWatchTotal->setVisible(showWatchOnly); // show watchonly total balance
+ ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active)
+ ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label
+ ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line
+ ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
+ ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watch-only immature balance
+ ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance
+ ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance
}
void OverviewPage::setClientModel(ClientModel *model)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 7c0c95c459..a9f1566d62 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -90,7 +90,7 @@ static QList<QString> savedPaymentRequests;
static void ReportInvalidCertificate(const QSslCertificate& cert)
{
- qWarning() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
+ qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
}
//
@@ -424,7 +424,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
else
emit message(tr("URI handling"),
- tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
+ tr("URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
CClientUIInterface::ICON_WARNING);
return;
@@ -438,7 +438,7 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (!readPaymentRequest(s, request))
{
emit message(tr("Payment request file handling"),
- tr("Payment request file can not be read! This can be caused by an invalid payment request file."),
+ tr("Payment request file cannot be read! This can be caused by an invalid payment request file."),
CClientUIInterface::ICON_WARNING);
}
else if (processPaymentRequest(request, recipient))
@@ -663,7 +663,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
{
qWarning() << "PaymentServer::netRequestFinished : Error parsing payment request";
emit message(tr("Payment request error"),
- tr("Payment request can not be parsed!"),
+ tr("Payment request cannot be parsed!"),
CClientUIInterface::MSG_ERROR);
}
else if (processPaymentRequest(request, recipient))
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 981d063c49..cfa05300cf 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -5,6 +5,8 @@
#include "peertablemodel.h"
#include "clientmodel.h"
+#include "guiconstants.h"
+#include "guiutil.h"
#include "net.h"
#include "sync.h"
@@ -15,8 +17,8 @@
bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
{
- const CNodeStats *pLeft = &(left.nodestats);
- const CNodeStats *pRight = &(right.nodestats);
+ const CNodeStats *pLeft = &(left.nodeStats);
+ const CNodeStats *pRight = &(right.nodeStats);
if (order == Qt::DescendingOrder)
std::swap(pLeft, pRight);
@@ -27,8 +29,8 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
return pLeft->addrName.compare(pRight->addrName) < 0;
case PeerTableModel::Subversion:
return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
- case PeerTableModel::Height:
- return pLeft->nStartingHeight < pRight->nStartingHeight;
+ case PeerTableModel::Ping:
+ return pLeft->dPingTime < pRight->dPingTime;
}
return false;
@@ -48,7 +50,8 @@ public:
std::map<NodeId, int> mapNodeRows;
/** Pull a full list of peers from vNodes into our cache */
- void refreshPeers() {
+ void refreshPeers()
+ {
{
TRY_LOCK(cs_vNodes, lockNodes);
if (!lockNodes)
@@ -63,21 +66,21 @@ public:
BOOST_FOREACH(CNode* pnode, vNodes)
{
CNodeCombinedStats stats;
- stats.statestats.nMisbehavior = -1;
- pnode->copyStats(stats.nodestats);
+ stats.nodeStateStats.nMisbehavior = 0;
+ stats.nodeStateStats.nSyncHeight = -1;
+ stats.fNodeStateStatsAvailable = false;
+ pnode->copyStats(stats.nodeStats);
cachedNodeStats.append(stats);
}
}
- // if we can, retrieve the CNodeStateStats for each node.
+ // Try to retrieve the CNodeStateStats for each node.
{
TRY_LOCK(cs_main, lockMain);
if (lockMain)
{
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
- {
- GetNodeStateStats(stats.nodestats.nodeid, stats.statestats);
- }
+ stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats);
}
}
@@ -89,9 +92,7 @@ public:
mapNodeRows.clear();
int row = 0;
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
- {
- mapNodeRows.insert(std::pair<NodeId, int>(stats.nodestats.nodeid, row++));
- }
+ mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
}
int size()
@@ -103,18 +104,18 @@ public:
{
if(idx >= 0 && idx < cachedNodeStats.size()) {
return &cachedNodeStats[idx];
- }
- else
- {
+ } else {
return 0;
}
}
};
PeerTableModel::PeerTableModel(ClientModel *parent) :
- QAbstractTableModel(parent),clientModel(parent),timer(0)
+ QAbstractTableModel(parent),
+ clientModel(parent),
+ timer(0)
{
- columns << tr("Address") << tr("User Agent") << tr("Start Height");
+ columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
priv = new PeerTablePriv();
// default to unsorted
priv->sortColumn = -1;
@@ -122,14 +123,14 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
// set up timer for auto refresh
timer = new QTimer();
connect(timer, SIGNAL(timeout()), SLOT(refresh()));
+ timer->setInterval(MODEL_UPDATE_DELAY);
// load initial data
refresh();
}
-void PeerTableModel::startAutoRefresh(int msecs)
+void PeerTableModel::startAutoRefresh()
{
- timer->setInterval(1000);
timer->start();
}
@@ -147,7 +148,7 @@ int PeerTableModel::rowCount(const QModelIndex &parent) const
int PeerTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
- return 3;
+ return columns.length();;
}
QVariant PeerTableModel::data(const QModelIndex &index, int role) const
@@ -157,18 +158,21 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());
- if(role == Qt::DisplayRole)
- {
+ if (role == Qt::DisplayRole) {
switch(index.column())
{
case Address:
- return QVariant(rec->nodestats.addrName.c_str());
+ return QString::fromStdString(rec->nodeStats.addrName);
case Subversion:
- return QVariant(rec->nodestats.cleanSubVer.c_str());
- case Height:
- return rec->nodestats.nStartingHeight;
+ return QString::fromStdString(rec->nodeStats.cleanSubVer);
+ case Ping:
+ return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
}
+ } else if (role == Qt::TextAlignmentRole) {
+ if (index.column() == Ping)
+ return (int)(Qt::AlignRight | Qt::AlignVCenter);
}
+
return QVariant();
}
@@ -208,7 +212,8 @@ QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent
}
}
-const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) {
+const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
+{
return priv->index(idx);
}
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index 385bf0e0c1..38f2662f89 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -19,8 +19,9 @@ class QTimer;
QT_END_NAMESPACE
struct CNodeCombinedStats {
- CNodeStats nodestats;
- CNodeStateStats statestats;
+ CNodeStats nodeStats;
+ CNodeStateStats nodeStateStats;
+ bool fNodeStateStatsAvailable;
};
class NodeLessThan
@@ -47,13 +48,13 @@ public:
explicit PeerTableModel(ClientModel *parent = 0);
const CNodeCombinedStats *getNodeStats(int idx);
int getRowByNodeId(NodeId nodeid);
- void startAutoRefresh(int msecs);
+ void startAutoRefresh();
void stopAutoRefresh();
enum ColumnIndex {
Address = 0,
Subversion = 1,
- Height = 2
+ Ping = 2
};
/** @name Methods overridden from QAbstractTableModel
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
index b5a998f9f5..9e3976644e 100644
--- a/src/qt/recentrequeststablemodel.cpp
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -79,10 +79,17 @@ QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) cons
case Amount:
if (rec->recipient.amount == 0 && role == Qt::DisplayRole)
return tr("(no amount)");
+ else if (role == Qt::EditRole)
+ return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount, false, BitcoinUnits::separatorNever);
else
return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount);
}
}
+ else if (role == Qt::TextAlignmentRole)
+ {
+ if (index.column() == Amount)
+ return (int)(Qt::AlignRight|Qt::AlignVCenter);
+ }
return QVariant();
}
diff --git a/src/qt/res/icons/toolbar.png b/src/qt/res/icons/toolbar.png
deleted file mode 100644
index c82d96519c..0000000000
--- a/src/qt/res/icons/toolbar.png
+++ /dev/null
Binary files differ
diff --git a/src/qt/res/icons/toolbar_testnet.png b/src/qt/res/icons/toolbar_testnet.png
deleted file mode 100644
index 5995bc0667..0000000000
--- a/src/qt/res/icons/toolbar_testnet.png
+++ /dev/null
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index e1f40ddd09..11089b2497 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -10,6 +10,7 @@
#include "peertablemodel.h"
#include "main.h"
+#include "chainparams.h"
#include "rpcserver.h"
#include "rpcclient.h"
#include "util.h"
@@ -200,12 +201,9 @@ RPCConsole::RPCConsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::RPCConsole),
clientModel(0),
- historyPtr(0)
+ historyPtr(0),
+ cachedNodeid(-1)
{
- detailNodeStats = CNodeCombinedStats();
- detailNodeStats.nodestats.nodeid = -1;
- detailNodeStats.statestats.nMisbehavior = -1;
-
ui->setupUi(this);
GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
@@ -233,6 +231,7 @@ RPCConsole::RPCConsole(QWidget *parent) :
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
ui->detailWidget->hide();
+ ui->peerHeading->setText(tr("Select a peer to view detailed information."));
clear();
}
@@ -303,11 +302,11 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
- columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(ui->peerWidget, MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
+ ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
+ ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
- // connect the peerWidget's selection model to our peerSelected() handler
- QItemSelectionModel *peerSelectModel = ui->peerWidget->selectionModel();
- connect(peerSelectModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ // connect the peerWidget selection model to our peerSelected() handler
+ connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
@@ -521,30 +520,24 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti
{
Q_UNUSED(deselected);
- if (selected.indexes().isEmpty())
+ if (!clientModel || selected.indexes().isEmpty())
return;
- // mark the cached banscore as unknown
- detailNodeStats.statestats.nMisbehavior = -1;
-
const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
-
if (stats)
- {
- detailNodeStats.nodestats.nodeid = stats->nodestats.nodeid;
updateNodeDetail(stats);
- ui->detailWidget->show();
- ui->detailWidget->setDisabled(false);
- }
}
void RPCConsole::peerLayoutChanged()
{
+ if (!clientModel)
+ return;
+
const CNodeCombinedStats *stats = NULL;
- bool fUnselect = false, fReselect = false, fDisconnected = false;
+ bool fUnselect = false;
+ bool fReselect = false;
- if (detailNodeStats.nodestats.nodeid == -1)
- // no node selected yet
+ if (cachedNodeid == -1) // no node selected yet
return;
// find the currently selected row
@@ -557,14 +550,15 @@ void RPCConsole::peerLayoutChanged()
// check if our detail node has a row in the table (it may not necessarily
// be at selectedRow since its position can change after a layout change)
- int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(detailNodeStats.nodestats.nodeid);
+ int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
if (detailNodeRow < 0)
{
// detail node dissapeared from table (node disconnected)
fUnselect = true;
- fDisconnected = true;
- detailNodeStats.nodestats.nodeid = 0;
+ cachedNodeid = -1;
+ ui->detailWidget->hide();
+ ui->peerHeading->setText(tr("Select a peer to view detailed information."));
}
else
{
@@ -592,85 +586,73 @@ void RPCConsole::peerLayoutChanged()
if (stats)
updateNodeDetail(stats);
-
- if (fDisconnected)
- {
- ui->peerHeading->setText(QString(tr("Peer Disconnected")));
- ui->detailWidget->setDisabled(true);
- QDateTime dt = QDateTime::fromTime_t(detailNodeStats.nodestats.nLastSend);
- if (detailNodeStats.nodestats.nLastSend)
- ui->peerLastSend->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
- dt.setTime_t(detailNodeStats.nodestats.nLastRecv);
- if (detailNodeStats.nodestats.nLastRecv)
- ui->peerLastRecv->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
- dt.setTime_t(detailNodeStats.nodestats.nTimeConnected);
- ui->peerConnTime->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
- }
}
-void RPCConsole::updateNodeDetail(const CNodeCombinedStats *combinedStats)
+void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
{
- CNodeStats stats = combinedStats->nodestats;
-
- // keep a copy of timestamps, used to display dates upon disconnect
- detailNodeStats.nodestats.nLastSend = stats.nLastSend;
- detailNodeStats.nodestats.nLastRecv = stats.nLastRecv;
- detailNodeStats.nodestats.nTimeConnected = stats.nTimeConnected;
+ // Update cached nodeid
+ cachedNodeid = stats->nodeStats.nodeid;
// update the detail ui with latest node information
- ui->peerHeading->setText(QString("<b>%1</b>").arg(tr("Node Detail")));
- ui->peerAddr->setText(QString(stats.addrName.c_str()));
- ui->peerServices->setText(GUIUtil::formatServicesStr(stats.nServices));
- ui->peerLastSend->setText(stats.nLastSend ? GUIUtil::formatDurationStr(GetTime() - stats.nLastSend) : tr("never"));
- ui->peerLastRecv->setText(stats.nLastRecv ? GUIUtil::formatDurationStr(GetTime() - stats.nLastRecv) : tr("never"));
- ui->peerBytesSent->setText(FormatBytes(stats.nSendBytes));
- ui->peerBytesRecv->setText(FormatBytes(stats.nRecvBytes));
- ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats.nTimeConnected));
- ui->peerPingTime->setText(stats.dPingTime == 0 ? tr("N/A") : QString(tr("%1 secs")).arg(QString::number(stats.dPingTime, 'f', 3)));
- ui->peerVersion->setText(QString("%1").arg(stats.nVersion));
- ui->peerSubversion->setText(QString(stats.cleanSubVer.c_str()));
- ui->peerDirection->setText(stats.fInbound ? tr("Inbound") : tr("Outbound"));
- ui->peerHeight->setText(QString("%1").arg(stats.nStartingHeight));
- ui->peerSyncNode->setText(stats.fSyncNode ? tr("Yes") : tr("No"));
-
- // if we can, display the peer's ban score
- CNodeStateStats statestats = combinedStats->statestats;
- if (statestats.nMisbehavior >= 0)
- {
- // we have a new nMisbehavor value - update the cache
- detailNodeStats.statestats.nMisbehavior = statestats.nMisbehavior;
+ QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName));
+ if (!stats->nodeStats.addrLocal.empty())
+ peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
+ ui->peerHeading->setText(peerAddrDetails);
+ ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
+ ui->peerLastSend->setText(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nLastSend) : tr("never"));
+ ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nLastRecv) : tr("never"));
+ ui->peerBytesSent->setText(FormatBytes(stats->nodeStats.nSendBytes));
+ ui->peerBytesRecv->setText(FormatBytes(stats->nodeStats.nRecvBytes));
+ ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nTimeConnected));
+ ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
+ ui->peerVersion->setText(QString("%1").arg(stats->nodeStats.nVersion));
+ ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
+ ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
+ ui->peerHeight->setText(QString("%1").arg(stats->nodeStats.nStartingHeight));
+ ui->peerSyncNode->setText(stats->nodeStats.fSyncNode ? tr("Yes") : tr("No"));
+
+ // This check fails for example if the lock was busy and
+ // nodeStateStats couldn't be fetched.
+ if (stats->fNodeStateStatsAvailable) {
+ // Ban score is init to 0
+ ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior));
+
+ // Sync height is init to -1
+ if (stats->nodeStateStats.nSyncHeight > -1)
+ ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
+ else
+ ui->peerSyncHeight->setText(tr("Unknown"));
+ } else {
+ ui->peerBanScore->setText(tr("Fetching..."));
+ ui->peerSyncHeight->setText(tr("Fetching..."));
}
- // pull the ban score from cache. -1 means it hasn't been retrieved yet (lock busy).
- if (detailNodeStats.statestats.nMisbehavior >= 0)
- ui->peerBanScore->setText(QString("%1").arg(detailNodeStats.statestats.nMisbehavior));
- else
- ui->peerBanScore->setText(tr("Fetching..."));
+ ui->detailWidget->show();
}
-// We override the virtual resizeEvent of the QWidget to adjust tables column
-// sizes as the tables width is proportional to the dialogs width.
void RPCConsole::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
- columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
}
void RPCConsole::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
- // peerWidget needs a resize in case the dialog has non-default geometry
- columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
+ if (!clientModel)
+ return;
// start PeerTableModel auto refresh
- clientModel->getPeerTableModel()->startAutoRefresh(1000);
+ clientModel->getPeerTableModel()->startAutoRefresh();
}
void RPCConsole::hideEvent(QHideEvent *event)
{
QWidget::hideEvent(event);
+ if (!clientModel)
+ return;
+
// stop PeerTableModel auto refresh
clientModel->getPeerTableModel()->stopAutoRefresh();
}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 3aeff3eace..64bb5c29b3 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -44,19 +44,6 @@ public:
protected:
virtual bool eventFilter(QObject* obj, QEvent *event);
-private:
- /** show detailed information on ui about selected node */
- void updateNodeDetail(const CNodeCombinedStats *combinedStats);
-
- enum ColumnWidths
- {
- ADDRESS_COLUMN_WIDTH = 250,
- MINIMUM_COLUMN_WIDTH = 120
- };
-
- /** track the node that we are currently viewing detail on in the peers tab */
- CNodeCombinedStats detailNodeStats;
-
private slots:
void on_lineEdit_returnPressed();
void on_tabWidget_currentChanged(int index);
@@ -94,15 +81,23 @@ signals:
private:
static QString FormatBytes(quint64 bytes);
+ void startExecutor();
void setTrafficGraphRange(int mins);
+ /** show detailed information on ui about selected node */
+ void updateNodeDetail(const CNodeCombinedStats *stats);
+
+ enum ColumnWidths
+ {
+ ADDRESS_COLUMN_WIDTH = 200,
+ SUBVERSION_COLUMN_WIDTH = 100,
+ PING_COLUMN_WIDTH = 80
+ };
Ui::RPCConsole *ui;
ClientModel *clientModel;
QStringList history;
- GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
int historyPtr;
-
- void startExecutor();
+ NodeId cachedNodeid;
};
#endif // RPCCONSOLE_H
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 6f10ed5b0b..25e3d2a0dc 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -143,7 +143,7 @@ void SendCoinsDialog::on_sendButton_clicked()
foreach(const SendCoinsRecipient &rcp, recipients)
{
// generate bold amount string
- QString amount = "<b>" + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
+ QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
amount.append("</b>");
// generate monospace address string
QString address = "<span style='font-family: monospace;'>" + rcp.address;
@@ -211,7 +211,7 @@ void SendCoinsDialog::on_sendButton_clicked()
{
// append fee string if a fee is required
questionString.append("<hr /><span style='color:#aa0000;'>");
- questionString.append(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
+ questionString.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
questionString.append("</span> ");
questionString.append(tr("added as transaction fee"));
}
@@ -223,10 +223,10 @@ void SendCoinsDialog::on_sendButton_clicked()
foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
{
if(u != model->getOptionsModel()->getDisplayUnit())
- alternativeUnits.append(BitcoinUnits::formatWithUnit(u, totalAmount));
+ alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
}
questionString.append(tr("Total Amount %1 (= %2)")
- .arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount))
+ .arg(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount))
.arg(alternativeUnits.join(" " + tr("or") + " ")));
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index e0f56f8cd2..52545c3857 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -34,6 +34,12 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
GUIUtil::setupAddressWidget(ui->payTo, this);
// just a label for displaying bitcoin address(es)
ui->payTo_is->setFont(GUIUtil::bitcoinAddressFont());
+
+ // Connect signals
+ connect(ui->payAmount, SIGNAL(valueChanged()), this, SIGNAL(payAmountChanged()));
+ connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked()));
+ connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked()));
+ connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked()));
}
SendCoinsEntry::~SendCoinsEntry()
@@ -72,11 +78,6 @@ void SendCoinsEntry::setModel(WalletModel *model)
if (model && model->getOptionsModel())
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
- connect(ui->payAmount, SIGNAL(textChanged()), this, SIGNAL(payAmountChanged()));
- connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked()));
- connect(ui->deleteButton_is, SIGNAL(clicked()), this, SLOT(deleteClicked()));
- connect(ui->deleteButton_s, SIGNAL(clicked()), this, SLOT(deleteClicked()));
-
clear();
}
@@ -130,6 +131,13 @@ bool SendCoinsEntry::validate()
retval = false;
}
+ // Sending a zero amount is invalid
+ if (ui->payAmount->value(0) <= 0)
+ {
+ ui->payAmount->setValid(false);
+ retval = false;
+ }
+
// Reject dust outputs:
if (retval && GUIUtil::isDust(ui->payTo->text(), ui->payAmount->value())) {
ui->payAmount->setValid(false);
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 36e4d50e30..4f6e3169f5 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -11,11 +11,11 @@
#include "db.h"
#include "main.h"
#include "paymentserver.h"
+#include "script.h"
#include "transactionrecord.h"
#include "timedata.h"
#include "ui_interface.h"
#include "wallet.h"
-#include "script.h"
#include <stdint.h>
#include <string>
@@ -136,7 +136,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
strHTML += "<b>" + tr("Credit") + ":</b> ";
if (wtx.IsInMainChain())
- strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
+ strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
else
strHTML += "(" + tr("not accepted") + ")";
strHTML += "<br>";
@@ -146,7 +146,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
//
// Credit
//
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
}
else
{
@@ -197,9 +197,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
}
}
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
if(toSelf)
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, txout.nValue) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
}
if (fAllToMe)
@@ -207,13 +207,13 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
// Payment to self
int64_t nChange = wtx.GetChange();
int64_t nValue = nCredit - nChange;
- strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>";
- strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>";
+ strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
+ strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
}
int64_t nTxFee = nDebit - wtx.GetValueOut();
if (nTxFee > 0)
- strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nTxFee) + "<br>";
+ strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
}
else
{
@@ -222,14 +222,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
//
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if (wallet->IsMine(txin))
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if (wallet->IsMine(txout))
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
}
}
- strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet, true) + "<br>";
+ strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
//
// Message
@@ -275,10 +275,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
if(wallet->IsMine(txin))
- strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
+ strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
if(wallet->IsMine(txout))
- strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
+ strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
@@ -304,7 +304,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
}
- strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue);
+ strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
}
diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp
index 7293029787..f9546fddb5 100644
--- a/src/qt/transactionfilterproxy.cpp
+++ b/src/qt/transactionfilterproxy.cpp
@@ -24,7 +24,7 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) :
typeFilter(ALL_TYPES),
minAmount(0),
limitRows(-1),
- showInactive(false)
+ showInactive(true)
{
}
@@ -39,7 +39,7 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &
qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong());
int status = index.data(TransactionTableModel::StatusRole).toInt();
- if(!showInactive && status == TransactionStatus::Conflicted && type == TransactionRecord::Other)
+ if(!showInactive && status == TransactionStatus::Conflicted)
return false;
if(!(TYPE(type) & typeFilter))
return false;
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 7d29c212b3..d7bd25e08b 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -184,8 +184,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = chainActive.Height();
- status.hasConflicting = false;
-
if (!IsFinalTx(wtx, chainActive.Height() + 1))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
@@ -229,7 +227,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
if (status.depth < 0)
{
status.status = TransactionStatus::Conflicted;
- status.hasConflicting = !(wtx.GetConflicts(false).empty());
}
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
{
@@ -238,7 +235,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
- status.hasConflicting = !(wtx.GetConflicts(false).empty());
}
else if (status.depth < RecommendedNumConfirmations)
{
@@ -249,13 +245,13 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.status = TransactionStatus::Confirmed;
}
}
+
}
-bool TransactionRecord::statusUpdateNeeded(int64_t nConflictsReceived)
+bool TransactionRecord::statusUpdateNeeded()
{
AssertLockHeld(cs_main);
- return (status.cur_num_blocks != chainActive.Height() ||
- status.cur_num_conflicts != nConflictsReceived);
+ return status.cur_num_blocks != chainActive.Height();
}
QString TransactionRecord::getTxID() const
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index d3cfa77d97..626b7654c6 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -19,17 +19,9 @@ class TransactionStatus
{
public:
TransactionStatus():
- countsForBalance(false),
- sortKey(""),
- matures_in(0),
- status(Offline),
- hasConflicting(false),
- depth(0),
- open_for(0),
- cur_num_blocks(-1),
- cur_num_conflicts(-1)
- {
- }
+ countsForBalance(false), sortKey(""),
+ matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1)
+ { }
enum Status {
Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/
@@ -59,10 +51,6 @@ public:
/** @name Reported status
@{*/
Status status;
-
- // Has conflicting transactions spending same prevout
- bool hasConflicting;
-
qint64 depth;
qint64 open_for; /**< Timestamp if status==OpenUntilDate, otherwise number
of additional blocks that need to be mined before
@@ -71,10 +59,6 @@ public:
/** Current number of blocks (to know whether cached status is still valid) */
int cur_num_blocks;
-
- /** Number of conflicts received into wallet as of last status update */
- int64_t cur_num_conflicts;
-
};
/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has
@@ -152,7 +136,7 @@ public:
/** Return whether a status update is needed.
*/
- bool statusUpdateNeeded(int64_t nConflictsReceived);
+ bool statusUpdateNeeded();
};
#endif // TRANSACTIONRECORD_H
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 3605cc1bad..1647bc776f 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -5,7 +5,6 @@
#include "transactiontablemodel.h"
#include "addresstablemodel.h"
-#include "bitcoinunits.h"
#include "guiconstants.h"
#include "guiutil.h"
#include "optionsmodel.h"
@@ -168,7 +167,8 @@ public:
parent->endRemoveRows();
break;
case CT_UPDATED:
- emit parent->dataChanged(parent->index(lowerIndex, parent->Status), parent->index(upperIndex-1, parent->Amount));
+ // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
+ // visible transactions.
break;
}
}
@@ -189,21 +189,20 @@ public:
// stuck if the core is holding the locks for a longer time - for
// example, during a wallet rescan.
//
- // If a status update is needed (blocks or conflicts came in since last check),
- // update the status of this transaction from the wallet. Otherwise,
+ // If a status update is needed (blocks came in since last check),
+ // update the status of this transaction from the wallet. Otherwise,
// simply re-use the cached status.
TRY_LOCK(cs_main, lockMain);
if(lockMain)
{
TRY_LOCK(wallet->cs_wallet, lockWallet);
- if(lockWallet && rec->statusUpdateNeeded(wallet->nConflictsReceived))
+ if(lockWallet && rec->statusUpdateNeeded())
{
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end())
{
rec->updateStatus(mi->second);
- rec->status.cur_num_conflicts = wallet->nConflictsReceived;
}
}
}
@@ -347,7 +346,7 @@ QString TransactionTableModel::lookupAddress(const std::string &address, bool to
{
description += label + QString(" ");
}
- if(label.isEmpty() || walletModel->getOptionsModel()->getDisplayAddresses() || tooltip)
+ if(label.isEmpty() || tooltip)
{
description += QString("(") + QString::fromStdString(address) + QString(")");
}
@@ -369,8 +368,6 @@ QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const
return tr("Payment to yourself");
case TransactionRecord::Generated:
return tr("Mined");
- case TransactionRecord::Other:
- return tr("Other");
default:
return QString();
}
@@ -436,9 +433,9 @@ QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const
return QVariant();
}
-QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const
+QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
{
- QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit);
+ QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
if(showUnconfirmed)
{
if(!wtx->status.countsForBalance)
@@ -523,7 +520,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case ToAddress:
return formatTxToAddress(rec, false);
case Amount:
- return formatTxAmount(rec);
+ return formatTxAmount(rec, true, BitcoinUnits::separatorAlways);
}
break;
case Qt::EditRole:
@@ -546,13 +543,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
return formatTooltip(rec);
case Qt::TextAlignmentRole:
return column_alignments[index.column()];
- case Qt::BackgroundColorRole:
- if (rec->status.hasConflicting)
- return COLOR_HASCONFLICTING_BG;
- break;
case Qt::ForegroundRole:
- if (rec->status.hasConflicting)
- return COLOR_HASCONFLICTING;
// Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{
@@ -586,7 +577,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case ConfirmedRole:
return rec->status.countsForBalance;
case FormattedAmountRole:
- return formatTxAmount(rec, false);
+ // Used for copy/export, so don't include separators
+ return formatTxAmount(rec, false, BitcoinUnits::separatorNever);
case StatusRole:
return rec->status.status;
}
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index e8b6ed065d..2124d3dd1c 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -5,6 +5,8 @@
#ifndef TRANSACTIONTABLEMODEL_H
#define TRANSACTIONTABLEMODEL_H
+#include "bitcoinunits.h"
+
#include <QAbstractTableModel>
#include <QStringList>
@@ -78,7 +80,7 @@ private:
QString formatTxDate(const TransactionRecord *wtx) const;
QString formatTxType(const TransactionRecord *wtx) const;
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const;
- QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true) const;
+ QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::separatorStandard) const;
QString formatTooltip(const TransactionRecord *rec) const;
QVariant txStatusDecoration(const TransactionRecord *wtx) const;
QVariant txAddressDecoration(const TransactionRecord *wtx) const;
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index d6d210a561..7e8b71d8ea 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -123,6 +123,8 @@ TransactionView::TransactionView(QWidget *parent) :
view->setTabKeyNavigation(false);
view->setContextMenuPolicy(Qt::CustomContextMenu);
+ view->installEventFilter(this);
+
transactionView = view;
// Actions
@@ -480,3 +482,22 @@ void TransactionView::resizeEvent(QResizeEvent* event)
QWidget::resizeEvent(event);
columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress);
}
+
+// Need to override default Ctrl+C action for amount as default behaviour is just to copy DisplayRole text
+bool TransactionView::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::KeyPress)
+ {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
+ {
+ QModelIndex i = this->transactionView->currentIndex();
+ if (i.isValid() && i.column() == TransactionTableModel::Amount)
+ {
+ GUIUtil::setClipboard(i.data(TransactionTableModel::FormattedAmountRole).toString());
+ return true;
+ }
+ }
+ }
+ return QWidget::eventFilter(obj, event);
+}
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 7a89fa11ca..618efbc565 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -8,6 +8,7 @@
#include "guiutil.h"
#include <QWidget>
+#include <QKeyEvent>
class TransactionFilterProxy;
class WalletModel;
@@ -78,6 +79,8 @@ private:
virtual void resizeEvent(QResizeEvent* event);
+ bool eventFilter(QObject *obj, QEvent *event);
+
private slots:
void contextualMenu(const QPoint &);
void dateRangeChanged();
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 7317c32766..0ad123f39d 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -35,6 +35,8 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
{
+ fProcessingQueuedTransactions = false;
+
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
recentRequestsTableModel = new RecentRequestsTableModel(wallet, this);
@@ -162,14 +164,6 @@ void WalletModel::checkBalanceChanged()
void WalletModel::updateTransaction(const QString &hash, int status)
{
- if (status == CT_GOT_CONFLICT)
- {
- emit message(tr("Conflict Received"),
- tr("WARNING: Transaction may never be confirmed. Its input was seen being spent by another transaction on the network. Wait for confirmation!"),
- CClientUIInterface::MSG_WARNING);
- return;
- }
-
if(transactionTableModel)
transactionTableModel->updateTransaction(hash, status);
@@ -492,8 +486,15 @@ static void ShowProgress(WalletModel *walletmodel, const std::string &title, int
if (nProgress == 100)
{
fQueueNotifications = false;
- BOOST_FOREACH(const PAIRTYPE(uint256, ChangeType)& notification, vQueueNotifications)
- NotifyTransactionChanged(walletmodel, NULL, notification.first, notification.second);
+ if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
+ QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
+ for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
+ {
+ if (vQueueNotifications.size() - i <= 10)
+ QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
+
+ NotifyTransactionChanged(walletmodel, NULL, vQueueNotifications[i].first, vQueueNotifications[i].second);
+ }
std::vector<std::pair<uint256, ChangeType> >().swap(vQueueNotifications); // clear
}
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 7ad54ff8e6..2bb91d85a9 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -133,6 +133,7 @@ public:
qint64 getWatchImmatureBalance() const;
int getNumTransactions() const;
EncryptionStatus getEncryptionStatus() const;
+ bool processingQueuedTransactions() { return fProcessingQueuedTransactions; }
// Check address for validity
bool validateAddress(const QString &address);
@@ -196,6 +197,7 @@ public:
private:
CWallet *wallet;
+ bool fProcessingQueuedTransactions;
// Wallet has an options model for wallet-specific options
// (transaction fee, for example)
@@ -256,6 +258,8 @@ public slots:
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
void pollBalanceChanged();
+ /* Needed to update fProcessingQueuedTransactions through a QueuedConnection */
+ void setProcessingQueuedTransactions(bool value) { fProcessingQueuedTransactions = value; }
};
#endif // WALLETMODEL_H
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 1cef48344f..b40ddc0a2f 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -137,7 +137,7 @@ void WalletView::setWalletModel(WalletModel *walletModel)
void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
// Prevent balloon-spam when initial block download is in progress
- if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
+ if (!walletModel || walletModel->processingQueuedTransactions() || !clientModel || clientModel->inInitialBlockDownload())
return;
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
diff --git a/src/random.cpp b/src/random.cpp
new file mode 100644
index 0000000000..0d20d205ac
--- /dev/null
+++ b/src/random.cpp
@@ -0,0 +1,139 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 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 "random.h"
+
+#ifdef WIN32
+#include "compat.h" // for Windows API
+#endif
+#include "util.h" // for LogPrint()
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+static inline int64_t GetPerformanceCounter()
+{
+ int64_t nCounter = 0;
+#ifdef WIN32
+ QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
+#else
+ timeval t;
+ gettimeofday(&t, NULL);
+ nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
+#endif
+ return nCounter;
+}
+
+void RandAddSeed()
+{
+ // Seed with CPU performance counter
+ int64_t nCounter = GetPerformanceCounter();
+ RAND_add(&nCounter, sizeof(nCounter), 1.5);
+ OPENSSL_cleanse((void*)&nCounter, sizeof(nCounter));
+}
+
+void RandAddSeedPerfmon()
+{
+ RandAddSeed();
+
+ // This can take up to 2 seconds, so only do it every 10 minutes
+ static int64_t nLastPerfmon;
+ if (GetTime() < nLastPerfmon + 10 * 60)
+ return;
+ nLastPerfmon = GetTime();
+
+#ifdef WIN32
+ // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
+ // Seed with the entire set of perfmon data
+ std::vector <unsigned char> vData(250000,0);
+ long ret = 0;
+ unsigned long nSize = 0;
+ const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
+ while (true)
+ {
+ nSize = vData.size();
+ ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
+ if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
+ break;
+ vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially
+ }
+ RegCloseKey(HKEY_PERFORMANCE_DATA);
+ if (ret == ERROR_SUCCESS)
+ {
+ RAND_add(begin_ptr(vData), nSize, nSize/100.0);
+ OPENSSL_cleanse(begin_ptr(vData), nSize);
+ LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
+ } else {
+ static bool warned = false; // Warn only once
+ if (!warned)
+ {
+ LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
+ warned = true;
+ }
+ }
+#endif
+}
+
+bool GetRandBytes(unsigned char *buf, int num)
+{
+ if (RAND_bytes(buf, num) != 1) {
+ LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
+ return false;
+ }
+ return true;
+}
+
+uint64_t GetRand(uint64_t nMax)
+{
+ if (nMax == 0)
+ return 0;
+
+ // The range of the random source must be a multiple of the modulus
+ // to give every possible output value an equal possibility
+ uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
+ uint64_t nRand = 0;
+ do {
+ GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
+ } while (nRand >= nRange);
+ return (nRand % nMax);
+}
+
+int GetRandInt(int nMax)
+{
+ return GetRand(nMax);
+}
+
+uint256 GetRandHash()
+{
+ uint256 hash;
+ GetRandBytes((unsigned char*)&hash, sizeof(hash));
+ return hash;
+}
+
+uint32_t insecure_rand_Rz = 11;
+uint32_t insecure_rand_Rw = 11;
+void seed_insecure_rand(bool fDeterministic)
+{
+ // The seed values have some unlikely fixed points which we avoid.
+ if(fDeterministic)
+ {
+ insecure_rand_Rz = insecure_rand_Rw = 11;
+ } else {
+ uint32_t tmp;
+ do {
+ GetRandBytes((unsigned char*)&tmp, 4);
+ } while(tmp == 0 || tmp == 0x9068ffffU);
+ insecure_rand_Rz = tmp;
+ do {
+ GetRandBytes((unsigned char*)&tmp, 4);
+ } while(tmp == 0 || tmp == 0x464fffffU);
+ insecure_rand_Rw = tmp;
+ }
+}
diff --git a/src/random.h b/src/random.h
new file mode 100644
index 0000000000..a599b08478
--- /dev/null
+++ b/src/random.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 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_RANDOM_H
+#define BITCOIN_RANDOM_H
+
+#include "uint256.h"
+
+#include <stdint.h>
+
+/**
+ * Seed OpenSSL PRNG with additional entropy data
+ */
+void RandAddSeed();
+void RandAddSeedPerfmon();
+
+/**
+ * Functions to gather random data via the OpenSSL PRNG
+ */
+bool GetRandBytes(unsigned char *buf, int num);
+uint64_t GetRand(uint64_t nMax);
+int GetRandInt(int nMax);
+uint256 GetRandHash();
+
+/**
+ * Seed insecure_rand using the random pool.
+ * @param Deterministic Use a determinstic seed
+ */
+void seed_insecure_rand(bool fDeterministic = false);
+
+/**
+ * MWC RNG of George Marsaglia
+ * This is intended to be fast. It has a period of 2^59.3, though the
+ * least significant 16 bits only have a period of about 2^30.1.
+ *
+ * @return random value
+ */
+extern uint32_t insecure_rand_Rz;
+extern uint32_t insecure_rand_Rw;
+static inline uint32_t insecure_rand(void)
+{
+ insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
+ insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
+ return (insecure_rand_Rw << 16) + insecure_rand_Rz;
+}
+
+#endif // BITCOIN_RANDOM_H
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 253693e624..1e5198b85c 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -461,3 +461,73 @@ Value getblockchaininfo(const Array& params, bool fHelp)
obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
return obj;
}
+
+/* Comparison function for sorting the getchaintips heads. */
+struct CompareBlocksByHeight
+{
+ bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
+ {
+ /* Make sure that unequal blocks with the same height do not compare
+ equal. Use the pointers themselves to make a distinction. */
+
+ if (a->nHeight != b->nHeight)
+ return (a->nHeight > b->nHeight);
+
+ return a < b;
+ }
+};
+
+Value getchaintips(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getchaintips\n"
+ "Return information about all known tips in the block tree,"
+ " including the main chain as well as orphaned branches.\n"
+ "\nResult:\n"
+ "[\n"
+ " {\n"
+ " \"height\": xxxx, (numeric) height of the chain tip\n"
+ " \"hash\": \"xxxx\", (string) block hash of the tip\n"
+ " \"branchlen\": 0 (numeric) zero for main chain\n"
+ " },\n"
+ " {\n"
+ " \"height\": xxxx,\n"
+ " \"hash\": \"xxxx\",\n"
+ " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
+ " }\n"
+ "]\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getchaintips", "")
+ + HelpExampleRpc("getchaintips", "")
+ );
+
+ /* Build up a list of chain tips. We start with the list of all
+ known blocks, and successively remove blocks that appear as pprev
+ of another block. */
+ std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
+ BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
+ setTips.insert(item.second);
+ BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
+ {
+ const CBlockIndex* pprev = item.second->pprev;
+ if (pprev)
+ setTips.erase(pprev);
+ }
+
+ /* Construct the output array. */
+ Array res;
+ BOOST_FOREACH(const CBlockIndex* block, setTips)
+ {
+ Object obj;
+ obj.push_back(Pair("height", block->nHeight));
+ obj.push_back(Pair("hash", block->phashBlock->GetHex()));
+
+ const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
+ obj.push_back(Pair("branchlen", branchLen));
+
+ res.push_back(obj);
+ }
+
+ return res;
+}
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index 5edeecf933..a0921453cc 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -85,6 +85,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawmempool", 0 },
{ "estimatefee", 0 },
{ "estimatepriority", 0 },
+ { "prioritisetransaction", 1 },
+ { "prioritisetransaction", 2 },
};
class CRPCConvertTable
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index 4193f41b49..ff2361482b 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -72,16 +72,17 @@ Value importprivkey(const Array& params, bool fHelp)
"\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
"\nArguments:\n"
"1. \"bitcoinprivkey\" (string, required) The private key (see dumpprivkey)\n"
- "2. \"label\" (string, optional) an optional label\n"
+ "2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
+ "\nNote: This call can take minutes to complete if rescan is true.\n"
"\nExamples:\n"
"\nDump a private key\n"
+ HelpExampleCli("dumpprivkey", "\"myaddress\"") +
- "\nImport the private key\n"
+ "\nImport the private key with rescan\n"
+ HelpExampleCli("importprivkey", "\"mykey\"") +
- "\nImport using a label\n"
+ "\nImport using a label and without rescan\n"
+ HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
- "\nAs a json rpc call\n"
+ "\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
);
@@ -137,8 +138,21 @@ Value importaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 3)
throw runtime_error(
- "importaddress <address> [label] [rescan=true]\n"
- "Adds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend.");
+ "importaddress \"address\" ( \"label\" rescan )\n"
+ "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n"
+ "\nArguments:\n"
+ "1. \"address\" (string, required) The address\n"
+ "2. \"label\" (string, optional, default=\"\") An optional label\n"
+ "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
+ "\nNote: This call can take minutes to complete if rescan is true.\n"
+ "\nExamples:\n"
+ "\nImport an address with rescan\n"
+ + HelpExampleCli("importaddress", "\"myaddress\"") +
+ "\nImport using a label without rescan\n"
+ + HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") +
+ "\nAs a JSON-RPC call\n"
+ + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
+ );
CScript script;
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index c7621dc137..edab427cbf 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -10,6 +10,7 @@
#include "main.h"
#include "miner.h"
#include "pow.h"
+#include "core_io.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
@@ -252,11 +253,30 @@ Value prioritisetransaction(const Array& params, bool fHelp)
if (fHelp || params.size() != 3)
throw runtime_error(
"prioritisetransaction <txid> <priority delta> <fee delta>\n"
- "Accepts the transaction into mined blocks at a higher (or lower) priority");
+ "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
+ "\nArguments:\n"
+ "1. \"txid\" (string, required) The transaction id.\n"
+ "2. priority delta (numeric, required) The priority to add or subtract.\n"
+ " The transaction selection algorithm considers the tx as it would have a higher priority.\n"
+ " (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
+ "3. fee delta (numeric, required) The absolute fee value to add or subtract in bitcoin.\n"
+ " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
+ " considers the transaction as it would have paid a higher (or lower) fee.\n"
+ "\nResult\n"
+ "true (boolean) Returns true\n"
+ "\nExamples:\n"
+ + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 0.00010000")
+ + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 0.00010000")
+ );
uint256 hash;
hash.SetHex(params[0].get_str());
- mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), params[2].get_int64());
+
+ int64_t nAmount = 0;
+ if (params[2].get_real() != 0.0)
+ nAmount = AmountFromValue(params[2]);
+
+ mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
return true;
}
@@ -324,6 +344,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
);
std::string strMode = "template";
+ Value lpval = Value::null;
if (params.size() > 0)
{
const Object& oparam = params[0].get_obj();
@@ -336,6 +357,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
+ lpval = find_value(oparam, "longpollid");
}
if (strMode != "template")
@@ -347,8 +369,63 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
- // Update block
static unsigned int nTransactionsUpdatedLast;
+
+ if (lpval.type() != null_type)
+ {
+ // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
+ uint256 hashWatchedChain;
+ boost::system_time checktxtime;
+ unsigned int nTransactionsUpdatedLastLP;
+
+ if (lpval.type() == str_type)
+ {
+ // Format: <hashBestChain><nTransactionsUpdatedLast>
+ std::string lpstr = lpval.get_str();
+
+ hashWatchedChain.SetHex(lpstr.substr(0, 64));
+ nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
+ }
+ else
+ {
+ // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
+ hashWatchedChain = chainActive.Tip()->GetBlockHash();
+ nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
+ }
+
+ // Release the wallet and main lock while waiting
+#ifdef ENABLE_WALLET
+ if(pwalletMain)
+ LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet);
+#endif
+ LEAVE_CRITICAL_SECTION(cs_main);
+ {
+ checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
+
+ boost::unique_lock<boost::mutex> lock(csBestBlock);
+ while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
+ {
+ if (!cvBlockChange.timed_wait(lock, checktxtime))
+ {
+ // Timeout: Check transactions for update
+ if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
+ break;
+ checktxtime += boost::posix_time::seconds(10);
+ }
+ }
+ }
+ ENTER_CRITICAL_SECTION(cs_main);
+#ifdef ENABLE_WALLET
+ if(pwalletMain)
+ ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet);
+#endif
+
+ if (!IsRPCRunning())
+ throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
+ // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
+ }
+
+ // Update block
static CBlockIndex* pindexPrev;
static int64_t nStart;
static CBlockTemplate* pblocktemplate;
@@ -396,9 +473,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
Object entry;
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << tx;
- entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end())));
+ entry.push_back(Pair("data", EncodeHexTx(tx)));
entry.push_back(Pair("hash", txHash.GetHex()));
@@ -436,6 +511,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
result.push_back(Pair("transactions", transactions));
result.push_back(Pair("coinbaseaux", aux));
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
+ result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index cff795bdf4..bd992397b8 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -27,6 +27,19 @@ using namespace boost::assign;
using namespace json_spirit;
using namespace std;
+/**
+ * @note Do not add or change anything in the information returned by this
+ * method. `getinfo` exists for backwards-compatibilty only. It combines
+ * information from wildly different sources in the program, which is a mess,
+ * and is thus planned to be deprecated eventually.
+ *
+ * Based on the source of the information, new information should be added to:
+ * - `getblockchaininfo`,
+ * - `getnetworkinfo` or
+ * - `getwalletinfo`
+ *
+ * Or alternatively, create a specific query method for the information.
+ **/
Value getinfo(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index cf2c293caf..88e7c4ab07 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -79,6 +79,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
"\nbResult:\n"
"[\n"
" {\n"
+ " \"id\": n, (numeric) Peer index\n"
" \"addr\":\"host:port\", (string) The ip address and port of the peer\n"
" \"addrlocal\":\"ip:port\", (string) local address\n"
" \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
@@ -97,8 +98,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
" \"syncnode\" : true|false (booleamn) if sync node\n"
" }\n"
" ,...\n"
- "}\n"
-
+ "]\n"
"\nExamples:\n"
+ HelpExampleCli("getpeerinfo", "")
+ HelpExampleRpc("getpeerinfo", "")
@@ -113,6 +113,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
Object obj;
CNodeStateStats statestats;
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
+ obj.push_back(Pair("id", stats.nodeid));
obj.push_back(Pair("addr", stats.addrName));
if (!(stats.addrLocal.empty()))
obj.push_back(Pair("addrlocal", stats.addrLocal));
@@ -137,6 +138,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("syncheight", statestats.nSyncHeight));
}
obj.push_back(Pair("syncnode", stats.fSyncNode));
+ obj.push_back(Pair("whitelisted", stats.fWhitelisted));
ret.push_back(obj);
}
diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp
index 9e18ca847e..643208b3b6 100644
--- a/src/rpcprotocol.cpp
+++ b/src/rpcprotocol.cpp
@@ -93,8 +93,7 @@ string HTTPError(int nStatus, bool keepalive, bool headersOnly)
headersOnly, "text/plain");
}
-string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
- bool headersOnly, const char *contentType)
+string HTTPReplyHeader(int nStatus, bool keepalive, size_t contentLength, const char *contentType)
{
return strprintf(
"HTTP/1.1 %d %s\r\n"
@@ -103,17 +102,25 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
"Content-Length: %u\r\n"
"Content-Type: %s\r\n"
"Server: bitcoin-json-rpc/%s\r\n"
- "\r\n"
- "%s",
+ "\r\n",
nStatus,
httpStatusDescription(nStatus),
rfc1123Time(),
keepalive ? "keep-alive" : "close",
- (headersOnly ? 0 : strMsg.size()),
+ contentLength,
contentType,
- FormatFullVersion(),
- (headersOnly ? "" : strMsg.c_str())
- );
+ FormatFullVersion());
+}
+
+string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
+ bool headersOnly, const char *contentType)
+{
+ if (headersOnly)
+ {
+ return HTTPReplyHeader(nStatus, keepalive, 0, contentType);
+ } else {
+ return HTTPReplyHeader(nStatus, keepalive, strMsg.size(), contentType) + strMsg;
+ }
}
bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
@@ -194,14 +201,14 @@ int ReadHTTPHeaders(std::basic_istream<char>& stream, map<string, string>& mapHe
int ReadHTTPMessage(std::basic_istream<char>& stream, map<string,
string>& mapHeadersRet, string& strMessageRet,
- int nProto)
+ int nProto, size_t max_size)
{
mapHeadersRet.clear();
strMessageRet = "";
// Read header
int nLen = ReadHTTPHeaders(stream, mapHeadersRet);
- if (nLen < 0 || nLen > (int)MAX_SIZE)
+ if (nLen < 0 || (size_t)nLen > max_size)
return HTTP_INTERNAL_SERVER_ERROR;
// Read message
diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h
index 5627077bfb..8f05c08482 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -143,6 +143,8 @@ private:
std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
std::string HTTPError(int nStatus, bool keepalive,
bool headerOnly = false);
+std::string HTTPReplyHeader(int nStatus, bool keepalive, size_t contentLength,
+ const char *contentType = "application/json");
std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive,
bool headerOnly = false,
const char *contentType = "application/json");
@@ -151,7 +153,7 @@ bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto);
int ReadHTTPHeaders(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet);
int ReadHTTPMessage(std::basic_istream<char>& stream, std::map<std::string, std::string>& mapHeadersRet,
- std::string& strMessageRet, int nProto);
+ std::string& strMessageRet, int nProto, size_t max_size);
std::string JSONRPCRequest(const std::string& strMethod, const json_spirit::Array& params, const json_spirit::Value& id);
json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 2306b1b883..763615120a 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -5,6 +5,7 @@
#include "base58.h"
#include "core.h"
+#include "core_io.h"
#include "init.h"
#include "keystore.h"
#include "main.h"
@@ -36,8 +37,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeH
if (fIncludeHex)
out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
- if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
- {
+ if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
out.push_back(Pair("type", GetTxnOutputType(type)));
return;
}
@@ -57,13 +57,11 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
Array vin;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- {
+ BOOST_FOREACH(const CTxIn& txin, tx.vin) {
Object in;
if (tx.IsCoinBase())
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- else
- {
+ else {
in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
in.push_back(Pair("vout", (int64_t)txin.prevout.n));
Object o;
@@ -76,8 +74,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
}
entry.push_back(Pair("vin", vin));
Array vout;
- for (unsigned int i = 0; i < tx.vout.size(); i++)
- {
+ for (unsigned int i = 0; i < tx.vout.size(); i++) {
const CTxOut& txout = tx.vout[i];
Object out;
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
@@ -89,15 +86,12 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
}
entry.push_back(Pair("vout", vout));
- if (hashBlock != 0)
- {
+ if (hashBlock != 0) {
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end() && (*mi).second)
- {
+ if (mi != mapBlockIndex.end() && (*mi).second) {
CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
- {
+ if (chainActive.Contains(pindex)) {
entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
entry.push_back(Pair("time", pindex->GetBlockTime()));
entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
@@ -182,9 +176,7 @@ Value getrawtransaction(const Array& params, bool fHelp)
if (!GetTransaction(hash, tx, hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << tx;
- string strHex = HexStr(ssTx.begin(), ssTx.end());
+ string strHex = EncodeHexTx(tx);
if (!fVerbose)
return strHex;
@@ -245,11 +237,9 @@ Value listunspent(const Array& params, bool fHelp)
nMaxDepth = params[1].get_int();
set<CBitcoinAddress> setAddress;
- if (params.size() > 2)
- {
+ if (params.size() > 2) {
Array inputs = params[2].get_array();
- BOOST_FOREACH(Value& input, inputs)
- {
+ BOOST_FOREACH(Value& input, inputs) {
CBitcoinAddress address(input.get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
@@ -263,13 +253,11 @@ Value listunspent(const Array& params, bool fHelp)
vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
pwalletMain->AvailableCoins(vecOutputs, false);
- BOOST_FOREACH(const COutput& out, vecOutputs)
- {
+ BOOST_FOREACH(const COutput& out, vecOutputs) {
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
continue;
- if (setAddress.size())
- {
+ if (setAddress.size()) {
CTxDestination address;
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
continue;
@@ -284,18 +272,15 @@ Value listunspent(const Array& params, bool fHelp)
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
entry.push_back(Pair("vout", out.i));
CTxDestination address;
- if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
- {
+ if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
if (pwalletMain->mapAddressBook.count(address))
entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
}
entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
- if (pk.IsPayToScriptHash())
- {
+ if (pk.IsPayToScriptHash()) {
CTxDestination address;
- if (ExtractDestination(pk, address))
- {
+ if (ExtractDestination(pk, address)) {
const CScriptID& hash = boost::get<const CScriptID&>(address);
CScript redeemScript;
if (pwalletMain->GetCScript(hash, redeemScript))
@@ -352,8 +337,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
CMutableTransaction rawTx;
- BOOST_FOREACH(const Value& input, inputs)
- {
+ BOOST_FOREACH(const Value& input, inputs) {
const Object& o = input.get_obj();
uint256 txid = ParseHashO(o, "txid");
@@ -370,8 +354,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
}
set<CBitcoinAddress> setAddress;
- BOOST_FOREACH(const Pair& s, sendTo)
- {
+ BOOST_FOREACH(const Pair& s, sendTo) {
CBitcoinAddress address(s.name_);
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
@@ -388,9 +371,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
rawTx.vout.push_back(out);
}
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss << rawTx;
- return HexStr(ss.begin(), ss.end());
+ return EncodeHexTx(rawTx);
}
Value decoderawtransaction(const Array& params, bool fHelp)
@@ -444,15 +425,12 @@ Value decoderawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
);
- vector<unsigned char> txData(ParseHexV(params[0], "argument"));
- CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+ RPCTypeCheck(params, list_of(str_type));
+
CTransaction tx;
- try {
- ssData >> tx;
- }
- catch (std::exception &e) {
+
+ if (!DecodeHexTx(tx, params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
- }
Object result;
TxToJSON(tx, 0, result);
@@ -523,7 +501,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
" \"txid\":\"id\", (string, required) The transaction id\n"
" \"vout\":n, (numeric, required) The output number\n"
" \"scriptPubKey\": \"hex\", (string, required) script key\n"
- " \"redeemScript\": \"hex\" (string, required) redeem script\n"
+ " \"redeemScript\": \"hex\" (string, required for P2SH) redeem script\n"
" }\n"
" ,...\n"
" ]\n"
@@ -556,8 +534,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
vector<CMutableTransaction> txVariants;
- while (!ssData.empty())
- {
+ while (!ssData.empty()) {
try {
CMutableTransaction tx;
ssData >> tx;
@@ -596,12 +573,10 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fGivenKeys = false;
CBasicKeyStore tempKeystore;
- if (params.size() > 2 && params[2].type() != null_type)
- {
+ if (params.size() > 2 && params[2].type() != null_type) {
fGivenKeys = true;
Array keys = params[2].get_array();
- BOOST_FOREACH(Value k, keys)
- {
+ BOOST_FOREACH(Value k, keys) {
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
@@ -616,11 +591,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
// Add previous txouts given in the RPC call:
- if (params.size() > 1 && params[1].type() != null_type)
- {
+ if (params.size() > 1 && params[1].type() != null_type) {
Array prevTxs = params[1].get_array();
- BOOST_FOREACH(Value& p, prevTxs)
- {
+ BOOST_FOREACH(Value& p, prevTxs) {
if (p.type() != obj_type)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
@@ -655,12 +628,10 @@ Value signrawtransaction(const Array& params, bool fHelp)
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
- if (fGivenKeys && scriptPubKey.IsPayToScriptHash())
- {
+ if (fGivenKeys && scriptPubKey.IsPayToScriptHash()) {
RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
Value v = find_value(prevOut, "redeemScript");
- if (!(v == Value::null))
- {
+ if (!(v == Value::null)) {
vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
CScript redeemScript(rsData.begin(), rsData.end());
tempKeystore.AddCScript(redeemScript);
@@ -676,8 +647,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
#endif
int nHashType = SIGHASH_ALL;
- if (params.size() > 3 && params[3].type() != null_type)
- {
+ if (params.size() > 3 && params[3].type() != null_type) {
static map<string, int> mapSigHashValues =
boost::assign::map_list_of
(string("ALL"), int(SIGHASH_ALL))
@@ -697,12 +667,10 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
// Sign what we can:
- for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
- {
+ for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
CCoins coins;
- if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n))
- {
+ if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n)) {
fComplete = false;
continue;
}
@@ -714,8 +682,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
// ... and merge in other signatures:
- BOOST_FOREACH(const CMutableTransaction& txv, txVariants)
- {
+ BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
}
if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS, 0))
@@ -723,9 +690,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
Object result;
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << mergedTx;
- result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
+ result.push_back(Pair("hex", EncodeHexTx(mergedTx)));
result.push_back(Pair("complete", fComplete));
return result;
@@ -754,25 +719,18 @@ Value sendrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
);
+ RPCTypeCheck(params, list_of(str_type)(bool_type));
// parse hex string from parameter
- vector<unsigned char> txData(ParseHexV(params[0], "parameter"));
- CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
+ if (!DecodeHexTx(tx, params[0].get_str()))
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ uint256 hashTx = tx.GetHash();
bool fOverrideFees = false;
if (params.size() > 1)
fOverrideFees = params[1].get_bool();
- // deserialize binary data stream
- try {
- ssData >> tx;
- }
- catch (std::exception &e) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
- }
- const uint256 &hashTx = tx.GetHash();
-
CCoinsViewCache &view = *pcoinsTip;
CCoins existingCoins;
bool fHaveMempool = mempool.exists(hashTx);
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 48b87f5139..56064941f6 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -32,6 +32,7 @@ using namespace std;
static std::string strRPCUserColonPass;
+static bool fRPCRunning = false;
// 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;
@@ -134,11 +135,18 @@ vector<unsigned char> ParseHexO(const Object& o, string strKey)
string CRPCTable::help(string strCommand) const
{
string strRet;
+ string category;
set<rpcfn_type> setDone;
+ vector<pair<string, const CRPCCommand*> > vCommands;
+
for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
+ vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
+ sort(vCommands.begin(), vCommands.end());
+
+ BOOST_FOREACH(const PAIRTYPE(string, const CRPCCommand*)& command, vCommands)
{
- const CRPCCommand *pcmd = mi->second;
- string strMethod = mi->first;
+ const CRPCCommand *pcmd = command.second;
+ string strMethod = pcmd->name;
// We already filter duplicates, but these deprecated screw up the sort order
if (strMethod.find("label") != string::npos)
continue;
@@ -161,8 +169,20 @@ string CRPCTable::help(string strCommand) const
// Help text is returned in an exception
string strHelp = string(e.what());
if (strCommand == "")
+ {
if (strHelp.find('\n') != string::npos)
strHelp = strHelp.substr(0, strHelp.find('\n'));
+
+ if (category != pcmd->category)
+ {
+ if (!category.empty())
+ strRet += "\n";
+ category = pcmd->category;
+ string firstLetter = category.substr(0,1);
+ boost::to_upper(firstLetter);
+ strRet += "== " + firstLetter + category.substr(1) + " ==\n";
+ }
+ }
strRet += strHelp + "\n";
}
}
@@ -212,102 +232,105 @@ Value stop(const Array& params, bool fHelp)
static const CRPCCommand vRPCCommands[] =
-{ // name actor (function) okSafeMode threadSafe reqWallet
- // ------------------------ ----------------------- ---------- ---------- ---------
+{ // category name actor (function) okSafeMode threadSafe reqWallet
+ // --------------------- ------------------------ ----------------------- ---------- ---------- ---------
/* Overall control/query calls */
- { "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */
- { "help", &help, true, true, false },
- { "stop", &stop, true, true, false },
+ { "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */
+ { "control", "help", &help, true, true, false },
+ { "control", "stop", &stop, true, true, false },
/* P2P networking */
- { "getnetworkinfo", &getnetworkinfo, true, false, false },
- { "addnode", &addnode, true, true, false },
- { "getaddednodeinfo", &getaddednodeinfo, true, true, false },
- { "getconnectioncount", &getconnectioncount, true, false, false },
- { "getnettotals", &getnettotals, true, true, false },
- { "getpeerinfo", &getpeerinfo, true, false, false },
- { "ping", &ping, true, false, false },
+ { "network", "getnetworkinfo", &getnetworkinfo, true, false, false },
+ { "network", "addnode", &addnode, true, true, false },
+ { "network", "getaddednodeinfo", &getaddednodeinfo, true, true, false },
+ { "network", "getconnectioncount", &getconnectioncount, true, false, false },
+ { "network", "getnettotals", &getnettotals, true, true, false },
+ { "network", "getpeerinfo", &getpeerinfo, true, false, false },
+ { "network", "ping", &ping, true, false, false },
/* Block chain and UTXO */
- { "getblockchaininfo", &getblockchaininfo, true, false, false },
- { "getbestblockhash", &getbestblockhash, true, false, false },
- { "getblockcount", &getblockcount, true, false, false },
- { "getblock", &getblock, true, false, false },
- { "getblockhash", &getblockhash, true, false, false },
- { "getdifficulty", &getdifficulty, true, false, false },
- { "getrawmempool", &getrawmempool, true, false, false },
- { "gettxout", &gettxout, true, false, false },
- { "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
- { "verifychain", &verifychain, true, false, false },
+ { "blockchain", "getblockchaininfo", &getblockchaininfo, true, false, false },
+ { "blockchain", "getbestblockhash", &getbestblockhash, true, false, false },
+ { "blockchain", "getblockcount", &getblockcount, true, false, false },
+ { "blockchain", "getblock", &getblock, true, false, false },
+ { "blockchain", "getblockhash", &getblockhash, true, false, false },
+ { "blockchain", "getchaintips", &getchaintips, true, false, false },
+ { "blockchain", "getdifficulty", &getdifficulty, true, false, false },
+ { "blockchain", "getrawmempool", &getrawmempool, true, false, false },
+ { "blockchain", "gettxout", &gettxout, true, false, false },
+ { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
+ { "blockchain", "verifychain", &verifychain, true, false, false },
/* Mining */
- { "getblocktemplate", &getblocktemplate, true, false, false },
- { "getmininginfo", &getmininginfo, true, false, false },
- { "getnetworkhashps", &getnetworkhashps, true, false, false },
- { "prioritisetransaction", &prioritisetransaction, true, false, false },
- { "submitblock", &submitblock, true, true, false },
+ { "mining", "getblocktemplate", &getblocktemplate, true, false, false },
+ { "mining", "getmininginfo", &getmininginfo, true, false, false },
+ { "mining", "getnetworkhashps", &getnetworkhashps, true, false, false },
+ { "mining", "prioritisetransaction", &prioritisetransaction, true, false, false },
+ { "mining", "submitblock", &submitblock, true, true, false },
+
+#ifdef ENABLE_WALLET
+ /* Coin generation */
+ { "generating", "getgenerate", &getgenerate, true, false, false },
+ { "generating", "gethashespersec", &gethashespersec, true, false, false },
+ { "generating", "setgenerate", &setgenerate, true, true, false },
+#endif
/* Raw transactions */
- { "createrawtransaction", &createrawtransaction, true, false, false },
- { "decoderawtransaction", &decoderawtransaction, true, false, false },
- { "decodescript", &decodescript, true, false, false },
- { "getrawtransaction", &getrawtransaction, true, false, false },
- { "sendrawtransaction", &sendrawtransaction, false, false, false },
- { "signrawtransaction", &signrawtransaction, false, false, false }, /* uses wallet if enabled */
+ { "rawtransactions", "createrawtransaction", &createrawtransaction, true, false, false },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, false, false },
+ { "rawtransactions", "decodescript", &decodescript, true, false, false },
+ { "rawtransactions", "getrawtransaction", &getrawtransaction, true, false, false },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, false, false },
+ { "rawtransactions", "signrawtransaction", &signrawtransaction, false, false, false }, /* uses wallet if enabled */
/* Utility functions */
- { "createmultisig", &createmultisig, true, true , false },
- { "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
- { "verifymessage", &verifymessage, true, false, false },
- { "estimatefee", &estimatefee, true, true, false },
- { "estimatepriority", &estimatepriority, true, true, false },
+ { "util", "createmultisig", &createmultisig, true, true , false },
+ { "util", "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */
+ { "util", "verifymessage", &verifymessage, true, false, false },
+ { "util", "estimatefee", &estimatefee, true, true, false },
+ { "util", "estimatepriority", &estimatepriority, true, true, false },
#ifdef ENABLE_WALLET
/* Wallet */
- { "addmultisigaddress", &addmultisigaddress, true, false, true },
- { "backupwallet", &backupwallet, true, false, true },
- { "dumpprivkey", &dumpprivkey, true, false, true },
- { "dumpwallet", &dumpwallet, true, false, true },
- { "encryptwallet", &encryptwallet, true, false, true },
- { "getaccountaddress", &getaccountaddress, true, false, true },
- { "getaccount", &getaccount, true, false, true },
- { "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
- { "getbalance", &getbalance, false, false, true },
- { "getnewaddress", &getnewaddress, true, false, true },
- { "getrawchangeaddress", &getrawchangeaddress, true, false, true },
- { "getreceivedbyaccount", &getreceivedbyaccount, false, false, true },
- { "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
- { "gettransaction", &gettransaction, false, false, true },
- { "getunconfirmedbalance", &getunconfirmedbalance, false, false, true },
- { "getwalletinfo", &getwalletinfo, false, false, true },
- { "importprivkey", &importprivkey, true, false, true },
- { "importwallet", &importwallet, true, false, true },
- { "importaddress", &importaddress, true, false, true },
- { "keypoolrefill", &keypoolrefill, true, false, true },
- { "listaccounts", &listaccounts, false, false, true },
- { "listaddressgroupings", &listaddressgroupings, false, false, true },
- { "listlockunspent", &listlockunspent, false, false, true },
- { "listreceivedbyaccount", &listreceivedbyaccount, false, false, true },
- { "listreceivedbyaddress", &listreceivedbyaddress, false, false, true },
- { "listsinceblock", &listsinceblock, false, false, true },
- { "listtransactions", &listtransactions, false, false, true },
- { "listunspent", &listunspent, false, false, true },
- { "lockunspent", &lockunspent, true, false, true },
- { "move", &movecmd, false, false, true },
- { "sendfrom", &sendfrom, false, false, true },
- { "sendmany", &sendmany, false, false, true },
- { "sendtoaddress", &sendtoaddress, false, false, true },
- { "setaccount", &setaccount, true, false, true },
- { "settxfee", &settxfee, true, false, true },
- { "signmessage", &signmessage, true, false, true },
- { "walletlock", &walletlock, true, false, true },
- { "walletpassphrasechange", &walletpassphrasechange, true, false, true },
- { "walletpassphrase", &walletpassphrase, true, false, true },
-
- /* Wallet-enabled mining */
- { "getgenerate", &getgenerate, true, false, false },
- { "gethashespersec", &gethashespersec, true, false, false },
- { "setgenerate", &setgenerate, true, true, false },
+ { "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true },
+ { "wallet", "backupwallet", &backupwallet, true, false, true },
+ { "wallet", "dumpprivkey", &dumpprivkey, true, false, true },
+ { "wallet", "dumpwallet", &dumpwallet, true, false, true },
+ { "wallet", "encryptwallet", &encryptwallet, true, false, true },
+ { "wallet", "getaccountaddress", &getaccountaddress, true, false, true },
+ { "wallet", "getaccount", &getaccount, true, false, true },
+ { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
+ { "wallet", "getbalance", &getbalance, false, false, true },
+ { "wallet", "getnewaddress", &getnewaddress, true, false, true },
+ { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, false, true },
+ { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, false, true },
+ { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
+ { "wallet", "gettransaction", &gettransaction, false, false, true },
+ { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, false, true },
+ { "wallet", "getwalletinfo", &getwalletinfo, false, false, true },
+ { "wallet", "importprivkey", &importprivkey, true, false, true },
+ { "wallet", "importwallet", &importwallet, true, false, true },
+ { "wallet", "importaddress", &importaddress, true, false, true },
+ { "wallet", "keypoolrefill", &keypoolrefill, true, false, true },
+ { "wallet", "listaccounts", &listaccounts, false, false, true },
+ { "wallet", "listaddressgroupings", &listaddressgroupings, false, false, true },
+ { "wallet", "listlockunspent", &listlockunspent, false, false, true },
+ { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, false, true },
+ { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, false, true },
+ { "wallet", "listsinceblock", &listsinceblock, false, false, true },
+ { "wallet", "listtransactions", &listtransactions, false, false, true },
+ { "wallet", "listunspent", &listunspent, false, false, true },
+ { "wallet", "lockunspent", &lockunspent, true, false, true },
+ { "wallet", "move", &movecmd, false, false, true },
+ { "wallet", "sendfrom", &sendfrom, false, false, true },
+ { "wallet", "sendmany", &sendmany, false, false, true },
+ { "wallet", "sendtoaddress", &sendtoaddress, false, false, true },
+ { "wallet", "setaccount", &setaccount, true, false, true },
+ { "wallet", "settxfee", &settxfee, true, false, true },
+ { "wallet", "signmessage", &signmessage, true, false, true },
+ { "wallet", "walletlock", &walletlock, true, false, true },
+ { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, false, true },
+ { "wallet", "walletpassphrase", &walletpassphrase, true, false, true },
#endif // ENABLE_WALLET
};
@@ -531,7 +554,7 @@ void StartRPCThreads()
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
{
unsigned char rand_pwd[32];
- RAND_bytes(rand_pwd, 32);
+ GetRandBytes(rand_pwd, 32);
string strWhatAmI = "To use bitcoind";
if (mapArgs.count("-server"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
@@ -659,6 +682,7 @@ void StartRPCThreads()
rpc_worker_group = new boost::thread_group();
for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
+ fRPCRunning = true;
}
void StartDummyRPCThread()
@@ -671,12 +695,15 @@ void StartDummyRPCThread()
rpc_dummy_work = new asio::io_service::work(*rpc_io_service);
rpc_worker_group = new boost::thread_group();
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
+ fRPCRunning = true;
}
}
void StopRPCThreads()
{
if (rpc_io_service == NULL) return;
+ // Set this to false first, so that longpolling loops will exit when woken up
+ fRPCRunning = false;
// First, cancel all timers and acceptors
// This is not done automatically by ->stop(), and in some cases the destructor of
@@ -698,6 +725,7 @@ void StopRPCThreads()
deadlineTimers.clear();
rpc_io_service->stop();
+ cvBlockChange.notify_all();
if (rpc_worker_group != NULL)
rpc_worker_group->join_all();
delete rpc_dummy_work; rpc_dummy_work = NULL;
@@ -706,6 +734,11 @@ void StopRPCThreads()
delete rpc_io_service; rpc_io_service = NULL;
}
+bool IsRPCRunning()
+{
+ return fRPCRunning;
+}
+
void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
{
if (!err)
@@ -850,7 +883,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
else
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
- conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush;
+ conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, strReply.size()) << strReply << std::flush;
}
catch (Object& objError)
{
@@ -879,7 +912,7 @@ void ServiceConnection(AcceptedConnection *conn)
break;
// Read HTTP message headers and body
- ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto);
+ ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto, MAX_SIZE);
// HTTP Keep-Alive is false; close connection immediately
if (mapHeaders["connection"] == "close")
diff --git a/src/rpcserver.h b/src/rpcserver.h
index e32eb975a1..2248e8aeb2 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -40,6 +40,8 @@ void StartRPCThreads();
void StartDummyRPCThread();
/* Stop RPC threads */
void StopRPCThreads();
+/* Query whether RPC is running */
+bool IsRPCRunning();
/*
Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
@@ -69,6 +71,7 @@ typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool f
class CRPCCommand
{
public:
+ std::string category;
std::string name;
rpcfn_type actor;
bool okSafeMode;
@@ -203,5 +206,6 @@ 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);
+extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp);
#endif
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index e8c62fd37b..215da2ea12 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
+#include "core_io.h"
#include "rpcserver.h"
#include "init.h"
#include "net.h"
@@ -58,10 +59,6 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
- Array respends;
- BOOST_FOREACH(const uint256& respend, wtx.GetConflicts(false))
- respends.push_back(respend.GetHex());
- entry.push_back(Pair("respendsobserved", respends));
entry.push_back(Pair("time", wtx.GetTxTime()));
entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
@@ -641,16 +638,16 @@ Value getbalance(const Array& params, bool fHelp)
int64_t allFee;
string strSentAccount;
- list<pair<CTxDestination, int64_t> > listReceived;
- list<pair<CTxDestination, int64_t> > listSent;
+ list<COutputEntry> listReceived;
+ list<COutputEntry> listSent;
wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
if (wtx.GetDepthInMainChain() >= nMinDepth)
{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived)
- nBalance += r.second;
+ BOOST_FOREACH(const COutputEntry& r, listReceived)
+ nBalance += r.amount;
}
- BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listSent)
- nBalance -= r.second;
+ BOOST_FOREACH(const COutputEntry& s, listSent)
+ nBalance -= s.amount;
nBalance -= allFee;
}
return ValueFromAmount(nBalance);
@@ -1133,8 +1130,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
int64_t nFee;
string strSentAccount;
- list<pair<CTxDestination, int64_t> > listReceived;
- list<pair<CTxDestination, int64_t> > listSent;
+ list<COutputEntry> listReceived;
+ list<COutputEntry> listSent;
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
@@ -1144,15 +1141,16 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Sent
if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent)
+ BOOST_FOREACH(const COutputEntry& s, listSent)
{
Object entry;
- if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & ISMINE_WATCH_ONLY))
+ if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", strSentAccount));
- MaybePushAddress(entry, s.first);
+ MaybePushAddress(entry, s.destination);
entry.push_back(Pair("category", "send"));
- entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
+ entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
+ entry.push_back(Pair("vout", s.vout));
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
WalletTxToJSON(wtx, entry);
@@ -1163,18 +1161,18 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived)
+ BOOST_FOREACH(const COutputEntry& r, listReceived)
{
string account;
- if (pwalletMain->mapAddressBook.count(r.first))
- account = pwalletMain->mapAddressBook[r.first].name;
+ if (pwalletMain->mapAddressBook.count(r.destination))
+ account = pwalletMain->mapAddressBook[r.destination].name;
if (fAllAccounts || (account == strAccount))
{
Object entry;
- if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & ISMINE_WATCH_ONLY))
+ if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
entry.push_back(Pair("involvesWatchonly", true));
entry.push_back(Pair("account", account));
- MaybePushAddress(entry, r.first);
+ MaybePushAddress(entry, r.destination);
if (wtx.IsCoinBase())
{
if (wtx.GetDepthInMainChain() < 1)
@@ -1188,7 +1186,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
entry.push_back(Pair("category", "receive"));
}
- entry.push_back(Pair("amount", ValueFromAmount(r.second)));
+ entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
+ entry.push_back(Pair("vout", r.vout));
if (fLong)
WalletTxToJSON(wtx, entry);
ret.push_back(entry);
@@ -1240,6 +1239,7 @@ Value listtransactions(const Array& params, bool fHelp)
" \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
" 'move' category for moves outbound. It is positive for the 'receive' category,\n"
" and for the 'move' category for inbound funds.\n"
+ " \"vout\" : n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the \n"
" 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
@@ -1249,12 +1249,6 @@ Value listtransactions(const Array& params, bool fHelp)
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
" for 'send' and 'receive' category of transactions.\n"
@@ -1375,22 +1369,22 @@ Value listaccounts(const Array& params, bool fHelp)
const CWalletTx& wtx = (*it).second;
int64_t nFee;
string strSentAccount;
- list<pair<CTxDestination, int64_t> > listReceived;
- list<pair<CTxDestination, int64_t> > listSent;
+ list<COutputEntry> listReceived;
+ list<COutputEntry> listSent;
int nDepth = wtx.GetDepthInMainChain();
if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
continue;
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
mapAccountBalances[strSentAccount] -= nFee;
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent)
- mapAccountBalances[strSentAccount] -= s.second;
+ BOOST_FOREACH(const COutputEntry& s, listSent)
+ mapAccountBalances[strSentAccount] -= s.amount;
if (nDepth >= nMinDepth)
{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived)
- if (pwalletMain->mapAddressBook.count(r.first))
- mapAccountBalances[pwalletMain->mapAddressBook[r.first].name] += r.second;
+ BOOST_FOREACH(const COutputEntry& r, listReceived)
+ if (pwalletMain->mapAddressBook.count(r.destination))
+ mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
else
- mapAccountBalances[""] += r.second;
+ mapAccountBalances[""] += r.amount;
}
}
@@ -1424,18 +1418,13 @@ Value listsinceblock(const Array& params, bool fHelp)
" \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
" \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
" outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
+ " \"vout\" : n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
@@ -1514,12 +1503,6 @@ Value gettransaction(const Array& params, bool fHelp)
" \"blockindex\" : xx, (numeric) The block index\n"
" \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"txid\" : \"transactionid\", (string) The transaction id.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
" \"details\" : [\n"
@@ -1528,13 +1511,14 @@ Value gettransaction(const Array& params, bool fHelp)
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
" \"amount\" : x.xxx (numeric) The amount in btc\n"
+ " \"vout\" : n, (numeric) the vout value\n"
" }\n"
" ,...\n"
" ],\n"
" \"hex\" : \"data\" (string) Raw data for transaction\n"
"}\n"
- "\nbExamples\n"
+ "\nExamples:\n"
+ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
@@ -1567,9 +1551,7 @@ Value gettransaction(const Array& params, bool fHelp)
ListTransactions(wtx, "*", 0, false, details, filter);
entry.push_back(Pair("details", details));
- CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
- ssTx << static_cast<CTransaction>(wtx);
- string strHex = HexStr(ssTx.begin(), ssTx.end());
+ string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
entry.push_back(Pair("hex", strHex));
return entry;
diff --git a/src/script.cpp b/src/script.cpp
index 238a25e72d..942e8810db 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -5,13 +5,14 @@
#include "script.h"
+#include "crypto/ripemd160.h"
+#include "crypto/sha1.h"
+#include "crypto/sha2.h"
#include "core.h"
#include "hash.h"
#include "key.h"
#include "keystore.h"
-#include "crypto/sha1.h"
-#include "crypto/sha2.h"
-#include "crypto/ripemd160.h"
+#include "random.h"
#include "sync.h"
#include "uint256.h"
#include "util.h"
@@ -1097,7 +1098,6 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig
// Valid signature cache, to avoid doing expensive ECDSA signature checking
// twice for every transaction (once when accepted into memory pool, and
// again when accepted into the block chain)
-
class CSignatureCache
{
private:
@@ -1444,18 +1444,6 @@ unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
return nResult;
}
-
-class CKeyStoreIsMineVisitor : public boost::static_visitor<bool>
-{
-private:
- const CKeyStore *keystore;
-public:
- CKeyStoreIsMineVisitor(const CKeyStore *keystoreIn) : keystore(keystoreIn) { }
- bool operator()(const CNoDestination &dest) const { return false; }
- bool operator()(const CKeyID &keyID) const { return keystore->HaveKey(keyID); }
- bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); }
-};
-
isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
{
CScript script;
diff --git a/src/script.h b/src/script.h
index e36be2db9e..7cb863d1c9 100644
--- a/src/script.h
+++ b/src/script.h
@@ -166,7 +166,7 @@ private:
// If the input vector's most significant byte is 0x80, remove it from
// the result's msb and return a negative.
if (vch.back() & 0x80)
- return -(result & ~(0x80 << (8 * (vch.size() - 1))));
+ return -(result & ~(0x80ULL << (8 * (vch.size() - 1))));
return result;
}
@@ -809,6 +809,7 @@ bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int
bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags);
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
diff --git a/src/serialize.h b/src/serialize.h
index 5ac85554c6..f876efd9b5 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -830,6 +830,35 @@ struct ser_streamplaceholder
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
+class CSizeComputer
+{
+protected:
+ size_t nSize;
+
+public:
+ int nType;
+ int nVersion;
+
+ CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {}
+
+ CSizeComputer& write(const char *psz, int nSize)
+ {
+ this->nSize += nSize;
+ return *this;
+ }
+
+ template<typename T>
+ CSizeComputer& operator<<(const T& obj)
+ {
+ ::Serialize(*this, obj, nType, nVersion);
+ return (*this);
+ }
+
+ size_t size() const {
+ return nSize;
+ }
+};
+
/** Double ended buffer combining vector and stream-like interfaces.
*
* >> and << read and write unformatted data using the above serialization templates.
diff --git a/src/sync.h b/src/sync.h
index 077ed59b89..cd319e0171 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -84,6 +84,9 @@ typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;
/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
+/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
+typedef boost::condition_variable CConditionVariable;
+
#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp
index 23dd74296c..a9798623ea 100644
--- a/src/test/canonical_tests.cpp
+++ b/src/test/canonical_tests.cpp
@@ -6,12 +6,11 @@
// Unit tests for canonical signatures
//
-
-
-#include "script.h"
-#include "util.h"
#include "data/sig_noncanonical.json.h"
#include "data/sig_canonical.json.h"
+#include "random.h"
+#include "script.h"
+#include "util.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
@@ -21,7 +20,6 @@
using namespace std;
using namespace json_spirit;
-
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 7bd98fa381..a17278b803 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -5,6 +5,7 @@
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha2.h"
+#include "random.h"
#include "util.h"
#include <vector>
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index d623e974b8..e3e1ccbf3c 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -272,6 +272,9 @@
["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+["2147483648 1", "BOOLOR 1", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
+["2147483648 1", "BOOLAND 1", "We cannot do BOOLAND on 5-byte integers"],
+
["1", "1 ENDIF", "ENDIF without IF"],
["1", "IF 1", "IF without ENDIF"],
["1 IF 1", "ENDIF", "IFs don't carry over"],
@@ -349,6 +352,9 @@
"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"],
+["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "nPubKeys > 20"],
+["0 'sig' 1 0", "CHECKMULTISIG 1", "nSigs > nPubKeys"],
+
["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"],
["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"],
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index 7546a3b1fe..082c65efed 100644
--- a/src/test/data/script_valid.json
+++ b/src/test/data/script_valid.json
@@ -10,6 +10,8 @@
[" 1 2 ", "2 EQUALVERIFY 1 EQUAL"],
["1", ""],
+["0x02 0x01 0x00", "", "all bytes are significant, not only the last one"],
+["0x09 0x00000000 0x00000000 0x10", "", "equals zero when cast to Int64"],
["0x01 0x0b", "11 EQUAL", "push 1 byte"],
["0x02 0x417a", "'Az' EQUAL"],
@@ -64,6 +66,7 @@
["0", "IF RETURN ENDIF 1", "RETURN only works if executed"],
["1 1", "VERIFY"],
+["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "values >4 bytes can be cast to boolean"],
["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"],
["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"],
@@ -126,6 +129,7 @@
["-9223372036854775807", "SIZE 8 EQUAL"],
["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"],
+["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "SIZE does not consume argument"],
["2 -2 ADD", "0 EQUAL"],
["2147483647 -2147483647 ADD", "0 EQUAL"],
diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp
index 60f11c147a..547cd1090c 100644
--- a/src/test/mruset_tests.cpp
+++ b/src/test/mruset_tests.cpp
@@ -4,6 +4,7 @@
#include "mruset.h"
+#include "random.h"
#include "util.h"
#include <set>
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 452cf084a7..2a0466e928 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -17,8 +17,6 @@ using namespace boost::assign;
typedef vector<unsigned char> valtype;
-extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-
BOOST_AUTO_TEST_SUITE(multisig_tests)
CScript
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index a1dc17ba36..51ff1ffbc9 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -15,9 +15,6 @@
using namespace std;
-// Test routines internal to script.cpp:
-extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-
// Helpers:
static std::vector<unsigned char>
Serialize(const CScript& s)
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index cba582e941..bc9f31c077 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -10,6 +10,8 @@
#include "key.h"
#include "keystore.h"
#include "main.h"
+#include "script.h"
+#include "core_io.h"
#include <fstream>
#include <stdint.h>
@@ -32,80 +34,8 @@ using namespace std;
using namespace json_spirit;
using namespace boost::algorithm;
-extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
-CScript
-ParseScript(string s)
-{
- CScript result;
-
- static map<string, opcodetype> mapOpNames;
-
- if (mapOpNames.size() == 0)
- {
- for (int op = 0; op <= OP_NOP10; op++)
- {
- // Allow OP_RESERVED to get into mapOpNames
- if (op < OP_NOP && op != OP_RESERVED)
- continue;
-
- const char* name = GetOpName((opcodetype)op);
- if (strcmp(name, "OP_UNKNOWN") == 0)
- continue;
- string strName(name);
- mapOpNames[strName] = (opcodetype)op;
- // Convenience: OP_ADD and just ADD are both recognized:
- replace_first(strName, "OP_", "");
- mapOpNames[strName] = (opcodetype)op;
- }
- }
-
- vector<string> words;
- split(words, s, is_any_of(" \t\n"), token_compress_on);
-
- BOOST_FOREACH(string w, words)
- {
- if (w.size() == 0)
- {
- // Empty string, ignore. (boost::split given '' will return one word)
- }
- else if (all(w, is_digit()) ||
- (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit())))
- {
- // Number
- int64_t n = atoi64(w);
- result << n;
- }
- else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end())))
- {
- // Raw hex data, inserted NOT pushed onto stack:
- std::vector<unsigned char> raw = ParseHex(string(w.begin()+2, w.end()));
- result.insert(result.end(), raw.begin(), raw.end());
- }
- else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'"))
- {
- // Single-quoted string, pushed as data. NOTE: this is poor-man's
- // parsing, spaces/tabs/newlines in single-quoted strings won't work.
- std::vector<unsigned char> value(w.begin()+1, w.end()-1);
- result << value;
- }
- else if (mapOpNames.count(w))
- {
- // opcode, e.g. OP_ADD or ADD:
- result << mapOpNames[w];
- }
- else
- {
- BOOST_ERROR("Parse error: " << s);
- return CScript();
- }
- }
-
- return result;
-}
-
Array
read_json(const std::string& jsondata)
{
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 423ae4a789..bff151cdda 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -2,15 +2,17 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <boost/test/unit_test.hpp>
-#include <iostream>
-
+#include "data/sighash.json.h"
#include "main.h"
-#include "util.h"
+#include "random.h"
#include "serialize.h"
+#include "script.h"
+#include "util.h"
#include "version.h"
-#include "data/sighash.json.h"
+#include <iostream>
+
+#include <boost/test/unit_test.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
@@ -18,8 +20,6 @@
using namespace json_spirit;
extern Array read_json(const std::string& jsondata);
-extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-
// Old script.cpp SignatureHash function
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
@@ -118,7 +118,7 @@ BOOST_AUTO_TEST_SUITE(sighash_tests)
BOOST_AUTO_TEST_CASE(sighash_test)
{
seed_insecure_rand(false);
-
+
#if defined(PRINT_SIGHASH_JSON)
std::cout << "[\n";
std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
@@ -205,10 +205,9 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest);
continue;
}
-
+
sh = SignatureHash(scriptCode, tx, nIn, nHashType);
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
}
}
BOOST_AUTO_TEST_SUITE_END()
-
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 11762c6ea0..a123f1d197 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -2,11 +2,13 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <boost/test/unit_test.hpp>
-#include <vector>
#include "main.h"
+#include "random.h"
#include "util.h"
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
#define SKIPLIST_LENGTH 300000
@@ -98,4 +100,3 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
}
BOOST_AUTO_TEST_SUITE_END()
-
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index bcd2f75f55..443b5853b2 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -4,9 +4,8 @@
#define BOOST_TEST_MODULE Bitcoin Test Suite
-
-
#include "main.h"
+#include "random.h"
#include "txdb.h"
#include "ui_interface.h"
#include "util.h"
@@ -89,4 +88,3 @@ bool ShutdownRequested()
{
return false;
}
-
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 238033f407..03919e7c7d 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -9,6 +9,7 @@
#include "keystore.h"
#include "main.h"
#include "script.h"
+#include "core_io.h"
#include <map>
#include <string>
@@ -24,7 +25,6 @@ using namespace boost::algorithm;
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
-extern CScript ParseScript(string s);
unsigned int ParseFlags(string strFlags){
unsigned int flags = 0;
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 0b071361d8..068b9f29c8 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -4,6 +4,7 @@
#include "util.h"
+#include "random.h"
#include "sync.h"
#include <stdint.h>
diff --git a/src/timedata.cpp b/src/timedata.cpp
index 8a095d26dc..4576786b96 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -49,6 +49,24 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime)
static CMedianFilter<int64_t> vTimeOffsets(200,0);
vTimeOffsets.input(nOffsetSample);
LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
+
+ // There is a known issue here (see issue #4521):
+ //
+ // - The structure vTimeOffsets contains up to 200 elements, after which
+ // any new element added to it will not increase its size, replacing the
+ // oldest element.
+ //
+ // - The condition to update nTimeOffset includes checking whether the
+ // number of elements in vTimeOffsets is odd, which will never happen after
+ // there are 200 elements.
+ //
+ // But in this case the 'bug' is protective against some attacks, and may
+ // actually explain why we've never seen attacks which manipulate the
+ // clock offset.
+ //
+ // So we should hold off on fixing this and clean it up as part of
+ // a timing cleanup that strengthens it in a number of other ways.
+ //
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
int64_t nMedian = vTimeOffsets.median();
@@ -74,7 +92,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime)
if (!fMatch)
{
fDone = true;
- string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly.");
+ string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly.");
strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index a852de5da8..29924fff09 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -206,7 +206,7 @@ public:
}
if ((delta-1) >= (int)history.size())
delta = history.size(); // Last bucket is catch-all
- entriesByConfirmations[delta-1].push_back(&entry);
+ entriesByConfirmations.at(delta-1).push_back(&entry);
}
for (size_t i = 0; i < entriesByConfirmations.size(); i++)
{
@@ -225,6 +225,12 @@ public:
seenTxConfirm(feeRate, minRelayFee, dPriority, i);
}
}
+
+ //After new samples are added, we have to clear the sorted lists,
+ //so they'll be resorted the next time someone asks for an estimate
+ sortedFeeSamples.clear();
+ sortedPrioritySamples.clear();
+
for (size_t i = 0; i < history.size(); i++) {
if (history[i].FeeSamples() + history[i].PrioritySamples() > 0)
LogPrint("estimatefee", "estimates: for confirming within %d blocks based on %d/%d samples, fee=%s, prio=%g\n",
@@ -232,8 +238,6 @@ public:
history[i].FeeSamples(), history[i].PrioritySamples(),
estimateFee(i+1).ToString(), estimatePriority(i+1));
}
- sortedFeeSamples.clear();
- sortedPrioritySamples.clear();
}
// Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
@@ -299,7 +303,7 @@ public:
size_t nPrevSize = 0;
for (int i = 0; i < nBlocksToConfirm; i++)
nPrevSize += history.at(i).PrioritySamples();
- size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1);
+ size_t index = min(nPrevSize + nBucketSize/2, sortedPrioritySamples.size()-1);
return sortedPrioritySamples[index];
}
@@ -315,16 +319,27 @@ public:
void Read(CAutoFile& filein, const CFeeRate& minRelayFee)
{
- filein >> nBestSeenHeight;
+ int nFileBestSeenHeight;
+ filein >> nFileBestSeenHeight;
size_t numEntries;
filein >> numEntries;
- history.clear();
+ if (numEntries <= 0 || numEntries > 10000)
+ throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entires.");
+
+ std::vector<CBlockAverage> fileHistory;
+
for (size_t i = 0; i < numEntries; i++)
{
CBlockAverage entry;
entry.Read(filein, minRelayFee);
- history.push_back(entry);
+ fileHistory.push_back(entry);
}
+
+ //Now that we've processed the entire fee estimate data file and not
+ //thrown any errors, we can copy it to our history
+ nBestSeenHeight = nFileBestSeenHeight;
+ history = fileHistory;
+ assert(history.size() > 0);
}
};
@@ -420,6 +435,7 @@ void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed
void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
{
// Remove transactions which depend on inputs of tx, recursively
+ list<CTransaction> result;
LOCK(cs);
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
@@ -601,14 +617,15 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
- if (base->GetCoins(txid, coins))
- return true;
+ // If an entry in the mempool exists, always return that one, as it's guaranteed to never
+ // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
+ // transactions. First checking the underlying cache risks returning a pruned entry instead.
CTransaction tx;
if (mempool.lookup(txid, tx)) {
coins = CCoins(tx, MEMPOOL_HEIGHT);
return true;
}
- return false;
+ return (base->GetCoins(txid, coins) && !coins.IsPruned());
}
bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
diff --git a/src/ui_interface.h b/src/ui_interface.h
index e9fcd91d41..b3df2b5a85 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -21,8 +21,7 @@ enum ChangeType
{
CT_NEW,
CT_UPDATED,
- CT_DELETED,
- CT_GOT_CONFLICT
+ CT_DELETED
};
/** Signals for UI communication. */
@@ -63,8 +62,6 @@ public:
/** Force blocking, modal message box dialog (not just OS notification) */
MODAL = 0x10000000U,
- /** Don't bring GUI to foreground. Use for messages during initialization */
- NOSHOWGUI = 0x20000000U,
/** Predefined combinations for certain default usage cases */
MSG_INFORMATION = ICON_INFORMATION,
diff --git a/src/uint256.cpp b/src/uint256.cpp
index 3392f1e9bc..08c05594fd 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -290,3 +290,46 @@ uint32_t uint256::GetCompact(bool fNegative) const
nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
return nCompact;
}
+
+static void inline HashMix(uint32_t& a, uint32_t& b, uint32_t& c)
+{
+ // Taken from lookup3, by Bob Jenkins.
+ a -= c; a ^= ((c << 4) | (c >> 28)); c += b;
+ b -= a; b ^= ((a << 6) | (a >> 26)); a += c;
+ c -= b; c ^= ((b << 8) | (b >> 24)); b += a;
+ a -= c; a ^= ((c << 16) | (c >> 16)); c += b;
+ b -= a; b ^= ((a << 19) | (a >> 13)); a += c;
+ c -= b; c ^= ((b << 4) | (b >> 28)); b += a;
+}
+
+static void inline HashFinal(uint32_t& a, uint32_t& b, uint32_t& c)
+{
+ // Taken from lookup3, by Bob Jenkins.
+ c ^= b; c -= ((b << 14) | (b >> 18));
+ a ^= c; a -= ((c << 11) | (c >> 21));
+ b ^= a; b -= ((a << 25) | (a >> 7));
+ c ^= b; c -= ((b << 16) | (b >> 16));
+ a ^= c; a -= ((c << 4) | (c >> 28));
+ b ^= a; b -= ((a << 14) | (a >> 18));
+ c ^= b; c -= ((b << 24) | (b >> 8));
+}
+
+uint64_t uint256::GetHash(const uint256 &salt) const
+{
+ uint32_t a, b, c;
+ a = b = c = 0xdeadbeef + (WIDTH << 2);
+
+ a += pn[0] ^ salt.pn[0];
+ b += pn[1] ^ salt.pn[1];
+ c += pn[2] ^ salt.pn[2];
+ HashMix(a, b, c);
+ a += pn[3] ^ salt.pn[3];
+ b += pn[4] ^ salt.pn[4];
+ c += pn[5] ^ salt.pn[5];
+ HashMix(a, b, c);
+ a += pn[6] ^ salt.pn[6];
+ b += pn[7] ^ salt.pn[7];
+ HashFinal(a, b, c);
+
+ return ((((uint64_t)b) << 32) | c);
+}
diff --git a/src/uint256.h b/src/uint256.h
index 82db7758c9..ad0a56f447 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -21,7 +21,7 @@ public:
template<unsigned int BITS>
class base_uint
{
-private:
+protected:
enum { WIDTH=BITS/32 };
uint32_t pn[WIDTH];
public:
@@ -322,6 +322,8 @@ public:
// implementation accident.
uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL);
uint32_t GetCompact(bool fNegative = false) const;
+
+ uint64_t GetHash(const uint256& salt) const;
};
#endif
diff --git a/src/univalue/univalue.cpp b/src/univalue/univalue.cpp
new file mode 100644
index 0000000000..afc208bffb
--- /dev/null
+++ b/src/univalue/univalue.cpp
@@ -0,0 +1,211 @@
+// Copyright 2014 BitPay Inc.
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <stdint.h>
+#include <ctype.h>
+#include <sstream>
+#include "univalue.h"
+
+using namespace std;
+
+static const UniValue nullValue;
+
+void UniValue::clear()
+{
+ typ = VNULL;
+ val.clear();
+ keys.clear();
+ values.clear();
+}
+
+bool UniValue::setNull()
+{
+ clear();
+ return true;
+}
+
+bool UniValue::setBool(bool val_)
+{
+ clear();
+ typ = VBOOL;
+ if (val_)
+ val = "1";
+ return true;
+}
+
+static bool validNumStr(const string& s)
+{
+ string tokenVal;
+ unsigned int consumed;
+ enum jtokentype tt = getJsonToken(tokenVal, consumed, s.c_str());
+ return (tt == JTOK_NUMBER);
+}
+
+bool UniValue::setNumStr(const string& val_)
+{
+ if (!validNumStr(val))
+ return false;
+
+ clear();
+ typ = VNUM;
+ val = val_;
+ return true;
+}
+
+bool UniValue::setInt(uint64_t val)
+{
+ string s;
+ ostringstream oss;
+
+ oss << val;
+
+ return setNumStr(oss.str());
+}
+
+bool UniValue::setInt(int64_t val)
+{
+ string s;
+ ostringstream oss;
+
+ oss << val;
+
+ return setNumStr(oss.str());
+}
+
+bool UniValue::setFloat(double val)
+{
+ string s;
+ ostringstream oss;
+
+ oss << val;
+
+ return setNumStr(oss.str());
+}
+
+bool UniValue::setStr(const string& val_)
+{
+ clear();
+ typ = VSTR;
+ val = val_;
+ return true;
+}
+
+bool UniValue::setArray()
+{
+ clear();
+ typ = VARR;
+ return true;
+}
+
+bool UniValue::setObject()
+{
+ clear();
+ typ = VOBJ;
+ return true;
+}
+
+bool UniValue::push_back(const UniValue& val)
+{
+ if (typ != VARR)
+ return false;
+
+ values.push_back(val);
+ return true;
+}
+
+bool UniValue::push_backV(const std::vector<UniValue>& vec)
+{
+ if (typ != VARR)
+ return false;
+
+ values.insert(values.end(), vec.begin(), vec.end());
+
+ return true;
+}
+
+bool UniValue::pushKV(const std::string& key, const UniValue& val)
+{
+ if (typ != VOBJ)
+ return false;
+
+ keys.push_back(key);
+ values.push_back(val);
+ return true;
+}
+
+bool UniValue::pushKVs(const UniValue& obj)
+{
+ if (typ != VOBJ || obj.typ != VOBJ)
+ return false;
+
+ for (unsigned int i = 0; i < obj.keys.size(); i++) {
+ keys.push_back(obj.keys[i]);
+ values.push_back(obj.values[i]);
+ }
+
+ return true;
+}
+
+int UniValue::findKey(const std::string& key) const
+{
+ for (unsigned int i = 0; i < keys.size(); i++) {
+ if (keys[i] == key)
+ return (int) i;
+ }
+
+ return -1;
+}
+
+bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
+{
+ for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin();
+ it != t.end(); it++) {
+ int idx = findKey(it->first);
+ if (idx < 0)
+ return false;
+
+ if (values[idx].getType() != it->second)
+ return false;
+ }
+
+ return true;
+}
+
+const UniValue& UniValue::operator[](const std::string& key) const
+{
+ if (typ != VOBJ)
+ return nullValue;
+
+ int index = findKey(key);
+ if (index < 0)
+ return nullValue;
+
+ return values[index];
+}
+
+const UniValue& UniValue::operator[](unsigned int index) const
+{
+ if (typ != VOBJ && typ != VARR)
+ return nullValue;
+ if (index >= values.size())
+ return nullValue;
+
+ return values[index];
+}
+
+const char *uvTypeName(UniValue::VType t)
+{
+ switch (t) {
+ case UniValue::VNULL: return "null";
+ case UniValue::VBOOL: return "bool";
+ case UniValue::VOBJ: return "object";
+ case UniValue::VARR: return "array";
+ case UniValue::VSTR: return "string";
+ case UniValue::VNUM: return "number";
+ }
+
+ // not reached
+ return NULL;
+}
+
diff --git a/src/univalue/univalue.h b/src/univalue/univalue.h
new file mode 100644
index 0000000000..0a7bf3cceb
--- /dev/null
+++ b/src/univalue/univalue.h
@@ -0,0 +1,155 @@
+// Copyright 2014 BitPay Inc.
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef __UNIVALUE_H__
+#define __UNIVALUE_H__
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <cassert>
+
+class UniValue {
+public:
+ enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
+
+ UniValue() { typ = VNULL; }
+ UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
+ typ = initialType;
+ val = initialStr;
+ }
+ UniValue(uint64_t val_) {
+ setInt(val_);
+ }
+ UniValue(int64_t val_) {
+ setInt(val_);
+ }
+ UniValue(int val_) {
+ setInt(val_);
+ }
+ UniValue(double val_) {
+ setFloat(val_);
+ }
+ UniValue(const std::string& val_) {
+ setStr(val_);
+ }
+ UniValue(const char *val_) {
+ std::string s(val_);
+ setStr(s);
+ }
+ ~UniValue() {}
+
+ void clear();
+
+ bool setNull();
+ bool setBool(bool val);
+ bool setNumStr(const std::string& val);
+ bool setInt(uint64_t val);
+ bool setInt(int64_t val);
+ bool setInt(int val) { return setInt((int64_t)val); }
+ bool setFloat(double val);
+ bool setStr(const std::string& val);
+ bool setArray();
+ bool setObject();
+
+ enum VType getType() const { return typ; }
+ std::string getValStr() const { return val; }
+ bool empty() const { return (values.size() == 0); }
+
+ size_t count() const { return values.size(); }
+
+ bool getBool() const { return isTrue(); }
+ bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes);
+ const UniValue& operator[](const std::string& key) const;
+ const UniValue& operator[](unsigned int index) const;
+ bool exists(const std::string& key) const { return (findKey(key) >= 0); }
+
+ bool isNull() const { return (typ == VNULL); }
+ bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
+ bool isFalse() const { return (!isTrue()); }
+ bool isBool() const { return (typ == VBOOL); }
+ bool isStr() const { return (typ == VSTR); }
+ bool isNum() const { return (typ == VNUM); }
+ bool isArray() const { return (typ == VARR); }
+ bool isObject() const { return (typ == VOBJ); }
+
+ bool push_back(const UniValue& val);
+ bool push_back(const std::string& val_) {
+ UniValue tmpVal(VSTR, val_);
+ return push_back(tmpVal);
+ }
+ bool push_back(const char *val_) {
+ std::string s(val_);
+ return push_back(s);
+ }
+ bool push_backV(const std::vector<UniValue>& vec);
+
+ bool pushKV(const std::string& key, const UniValue& val);
+ bool pushKV(const std::string& key, const std::string& val) {
+ UniValue tmpVal(VSTR, val);
+ return pushKV(key, tmpVal);
+ }
+ bool pushKV(const std::string& key, const char *val_) {
+ std::string val(val_);
+ return pushKV(key, val);
+ }
+ bool pushKV(const std::string& key, int64_t val) {
+ UniValue tmpVal(val);
+ return pushKV(key, tmpVal);
+ }
+ bool pushKV(const std::string& key, uint64_t val) {
+ UniValue tmpVal(val);
+ return pushKV(key, tmpVal);
+ }
+ bool pushKV(const std::string& key, int val) {
+ UniValue tmpVal((int64_t)val);
+ return pushKV(key, tmpVal);
+ }
+ bool pushKV(const std::string& key, double val) {
+ UniValue tmpVal(val);
+ return pushKV(key, tmpVal);
+ }
+ bool pushKVs(const UniValue& obj);
+
+ std::string write(unsigned int prettyIndent = 0,
+ unsigned int indentLevel = 0) const;
+
+ bool read(const char *raw);
+ bool read(const std::string& rawStr) {
+ return read(rawStr.c_str());
+ }
+
+private:
+ UniValue::VType typ;
+ std::string val; // numbers are stored as C++ strings
+ std::vector<std::string> keys;
+ std::vector<UniValue> values;
+
+ int findKey(const std::string& key) const;
+ void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
+ void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
+};
+
+enum jtokentype {
+ JTOK_ERR = -1,
+ JTOK_NONE = 0, // eof
+ JTOK_OBJ_OPEN,
+ JTOK_OBJ_CLOSE,
+ JTOK_ARR_OPEN,
+ JTOK_ARR_CLOSE,
+ JTOK_COLON,
+ JTOK_COMMA,
+ JTOK_KW_NULL,
+ JTOK_KW_TRUE,
+ JTOK_KW_FALSE,
+ JTOK_NUMBER,
+ JTOK_STRING,
+};
+
+extern enum jtokentype getJsonToken(std::string& tokenVal,
+ unsigned int& consumed, const char *raw);
+extern const char *uvTypeName(UniValue::VType t);
+
+#endif // __UNIVALUE_H__
diff --git a/src/univalue/univalue_read.cpp b/src/univalue/univalue_read.cpp
new file mode 100644
index 0000000000..405be3e81f
--- /dev/null
+++ b/src/univalue/univalue_read.cpp
@@ -0,0 +1,390 @@
+// Copyright 2014 BitPay Inc.
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <string.h>
+#include <vector>
+#include <stdio.h>
+#include "univalue.h"
+
+using namespace std;
+
+// convert hexadecimal string to unsigned integer
+static const char *hatoui(const char *first, const char *last,
+ unsigned int& out)
+{
+ unsigned int result = 0;
+ for (; first != last; ++first)
+ {
+ int digit;
+ if (isdigit(*first))
+ digit = *first - '0';
+
+ else if (*first >= 'a' && *first <= 'f')
+ digit = *first - 'a' + 10;
+
+ else if (*first >= 'A' && *first <= 'F')
+ digit = *first - 'A' + 10;
+
+ else
+ break;
+
+ result = 16 * result + digit;
+ }
+ out = result;
+
+ return first;
+}
+
+enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
+ const char *raw)
+{
+ tokenVal.clear();
+ consumed = 0;
+
+ const char *rawStart = raw;
+
+ while ((*raw) && (isspace(*raw))) // skip whitespace
+ raw++;
+
+ switch (*raw) {
+
+ case 0:
+ return JTOK_NONE;
+
+ case '{':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_OBJ_OPEN;
+ case '}':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_OBJ_CLOSE;
+ case '[':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_ARR_OPEN;
+ case ']':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_ARR_CLOSE;
+
+ case ':':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_COLON;
+ case ',':
+ raw++;
+ consumed = (raw - rawStart);
+ return JTOK_COMMA;
+
+ case 'n':
+ case 't':
+ case 'f':
+ if (!strncmp(raw, "null", 4)) {
+ raw += 4;
+ consumed = (raw - rawStart);
+ return JTOK_KW_NULL;
+ } else if (!strncmp(raw, "true", 4)) {
+ raw += 4;
+ consumed = (raw - rawStart);
+ return JTOK_KW_TRUE;
+ } else if (!strncmp(raw, "false", 5)) {
+ raw += 5;
+ consumed = (raw - rawStart);
+ return JTOK_KW_FALSE;
+ } else
+ return JTOK_ERR;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ // part 1: int
+ string numStr;
+
+ const char *first = raw;
+
+ const char *firstDigit = first;
+ if (!isdigit(*firstDigit))
+ firstDigit++;
+ if ((*firstDigit == '0') && isdigit(firstDigit[1]))
+ return JTOK_ERR;
+
+ numStr += *raw; // copy first char
+ raw++;
+
+ if ((*first == '-') && (!isdigit(*raw)))
+ return JTOK_ERR;
+
+ while ((*raw) && isdigit(*raw)) { // copy digits
+ numStr += *raw;
+ raw++;
+ }
+
+ // part 2: frac
+ if (*raw == '.') {
+ numStr += *raw; // copy .
+ raw++;
+
+ if (!isdigit(*raw))
+ return JTOK_ERR;
+ while ((*raw) && isdigit(*raw)) { // copy digits
+ numStr += *raw;
+ raw++;
+ }
+ }
+
+ // part 3: exp
+ if (*raw == 'e' || *raw == 'E') {
+ numStr += *raw; // copy E
+ raw++;
+
+ if (*raw == '-' || *raw == '+') { // copy +/-
+ numStr += *raw;
+ raw++;
+ }
+
+ if (!isdigit(*raw))
+ return JTOK_ERR;
+ while ((*raw) && isdigit(*raw)) { // copy digits
+ numStr += *raw;
+ raw++;
+ }
+ }
+
+ tokenVal = numStr;
+ consumed = (raw - rawStart);
+ return JTOK_NUMBER;
+ }
+
+ case '"': {
+ raw++; // skip "
+
+ string valStr;
+
+ while (*raw) {
+ if (*raw < 0x20)
+ return JTOK_ERR;
+
+ else if (*raw == '\\') {
+ raw++; // skip backslash
+
+ switch (*raw) {
+ case '"': valStr += "\""; break;
+ case '\\': valStr += "\\"; break;
+ case '/': valStr += "/"; break;
+ case 'b': valStr += "\b"; break;
+ case 'f': valStr += "\f"; break;
+ case 'n': valStr += "\n"; break;
+ case 'r': valStr += "\r"; break;
+ case 't': valStr += "\t"; break;
+
+ case 'u': {
+ char buf[4] = {0,0,0,0};
+ char *last = &buf[0];
+ unsigned int codepoint;
+ if (hatoui(raw + 1, raw + 1 + 4, codepoint) !=
+ raw + 1 + 4)
+ return JTOK_ERR;
+
+ if (codepoint <= 0x7f)
+ *last = (char)codepoint;
+ else if (codepoint <= 0x7FF) {
+ *last++ = (char)(0xC0 | (codepoint >> 6));
+ *last = (char)(0x80 | (codepoint & 0x3F));
+ } else if (codepoint <= 0xFFFF) {
+ *last++ = (char)(0xE0 | (codepoint >> 12));
+ *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
+ *last = (char)(0x80 | (codepoint & 0x3F));
+ }
+
+ valStr += buf;
+ raw += 4;
+ break;
+ }
+ default:
+ return JTOK_ERR;
+
+ }
+
+ raw++; // skip esc'd char
+ }
+
+ else if (*raw == '"') {
+ raw++; // skip "
+ break; // stop scanning
+ }
+
+ else {
+ valStr += *raw;
+ raw++;
+ }
+ }
+
+ tokenVal = valStr;
+ consumed = (raw - rawStart);
+ return JTOK_STRING;
+ }
+
+ default:
+ return JTOK_ERR;
+ }
+}
+
+bool UniValue::read(const char *raw)
+{
+ clear();
+
+ bool expectName = false;
+ bool expectColon = false;
+ vector<UniValue*> stack;
+
+ enum jtokentype tok = JTOK_NONE;
+ enum jtokentype last_tok = JTOK_NONE;
+ while (1) {
+ last_tok = tok;
+
+ string tokenVal;
+ unsigned int consumed;
+ tok = getJsonToken(tokenVal, consumed, raw);
+ if (tok == JTOK_NONE || tok == JTOK_ERR)
+ break;
+ raw += consumed;
+
+ switch (tok) {
+
+ case JTOK_OBJ_OPEN:
+ case JTOK_ARR_OPEN: {
+ VType utyp = (tok == JTOK_OBJ_OPEN ? VOBJ : VARR);
+ if (!stack.size()) {
+ if (utyp == VOBJ)
+ setObject();
+ else
+ setArray();
+ stack.push_back(this);
+ } else {
+ UniValue tmpVal(utyp);
+ UniValue *top = stack.back();
+ top->values.push_back(tmpVal);
+
+ UniValue *newTop = &(top->values.back());
+ stack.push_back(newTop);
+ }
+
+ if (utyp == VOBJ)
+ expectName = true;
+ break;
+ }
+
+ case JTOK_OBJ_CLOSE:
+ case JTOK_ARR_CLOSE: {
+ if (!stack.size() || expectColon || (last_tok == JTOK_COMMA))
+ return false;
+
+ VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR);
+ UniValue *top = stack.back();
+ if (utyp != top->getType())
+ return false;
+
+ stack.pop_back();
+ expectName = false;
+ break;
+ }
+
+ case JTOK_COLON: {
+ if (!stack.size() || expectName || !expectColon)
+ return false;
+
+ UniValue *top = stack.back();
+ if (top->getType() != VOBJ)
+ return false;
+
+ expectColon = false;
+ break;
+ }
+
+ case JTOK_COMMA: {
+ if (!stack.size() || expectName || expectColon ||
+ (last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN))
+ return false;
+
+ UniValue *top = stack.back();
+ if (top->getType() == VOBJ)
+ expectName = true;
+ break;
+ }
+
+ case JTOK_KW_NULL:
+ case JTOK_KW_TRUE:
+ case JTOK_KW_FALSE: {
+ if (!stack.size() || expectName || expectColon)
+ return false;
+
+ UniValue tmpVal;
+ switch (tok) {
+ case JTOK_KW_NULL:
+ // do nothing more
+ break;
+ case JTOK_KW_TRUE:
+ tmpVal.setBool(true);
+ break;
+ case JTOK_KW_FALSE:
+ tmpVal.setBool(false);
+ break;
+ default: /* impossible */ break;
+ }
+
+ UniValue *top = stack.back();
+ top->values.push_back(tmpVal);
+
+ break;
+ }
+
+ case JTOK_NUMBER: {
+ if (!stack.size() || expectName || expectColon)
+ return false;
+
+ UniValue tmpVal(VNUM, tokenVal);
+ UniValue *top = stack.back();
+ top->values.push_back(tmpVal);
+
+ break;
+ }
+
+ case JTOK_STRING: {
+ if (!stack.size())
+ return false;
+
+ UniValue *top = stack.back();
+
+ if (expectName) {
+ top->keys.push_back(tokenVal);
+ expectName = false;
+ expectColon = true;
+ } else {
+ UniValue tmpVal(VSTR, tokenVal);
+ top->values.push_back(tmpVal);
+ }
+
+ break;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ if (stack.size() != 0)
+ return false;
+
+ return true;
+}
+
diff --git a/src/univalue/univalue_write.cpp b/src/univalue/univalue_write.cpp
new file mode 100644
index 0000000000..1818f5c6f9
--- /dev/null
+++ b/src/univalue/univalue_write.cpp
@@ -0,0 +1,145 @@
+// Copyright 2014 BitPay Inc.
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <ctype.h>
+#include <stdio.h>
+#include "univalue.h"
+
+// TODO: Using UTF8
+
+using namespace std;
+
+static bool initEscapes;
+static const char *escapes[256];
+
+static void initJsonEscape()
+{
+ escapes['"'] = "\\\"";
+ escapes['\\'] = "\\\\";
+ escapes['/'] = "\\/";
+ escapes['\b'] = "\\b";
+ escapes['\f'] = "\\f";
+ escapes['\n'] = "\\n";
+ escapes['\r'] = "\\r";
+ escapes['\t'] = "\\t";
+
+ initEscapes = true;
+}
+
+static string json_escape(const string& inS)
+{
+ if (!initEscapes)
+ initJsonEscape();
+
+ string outS;
+ outS.reserve(inS.size() * 2);
+
+ for (unsigned int i = 0; i < inS.size(); i++) {
+ unsigned char ch = inS[i];
+ const char *escStr = escapes[ch];
+
+ if (escStr)
+ outS += escStr;
+
+ else if (isprint(ch))
+ outS += ch;
+
+ else {
+ char tmpesc[16];
+ sprintf(tmpesc, "\\u%04x", ch);
+ outS += tmpesc;
+ }
+ }
+
+ return outS;
+}
+
+string UniValue::write(unsigned int prettyIndent,
+ unsigned int indentLevel) const
+{
+ string s;
+ s.reserve(1024);
+
+ unsigned int modIndent = indentLevel;
+ if (modIndent == 0)
+ modIndent = 1;
+
+ switch (typ) {
+ case VNULL:
+ s += "null";
+ break;
+ case VOBJ:
+ writeObject(prettyIndent, modIndent, s);
+ break;
+ case VARR:
+ writeArray(prettyIndent, modIndent, s);
+ break;
+ case VSTR:
+ s += "\"" + json_escape(val) + "\"";
+ break;
+ case VNUM:
+ s += val;
+ break;
+ case VBOOL:
+ s += (val == "1" ? "true" : "false");
+ break;
+ }
+
+ return s;
+}
+
+static string spaceStr;
+
+static string indentStr(unsigned int prettyIndent, unsigned int indentLevel)
+{
+ unsigned int spaces = prettyIndent * indentLevel;
+ while (spaceStr.size() < spaces)
+ spaceStr += " ";
+
+ return spaceStr.substr(0, spaces);
+}
+
+void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
+{
+ s += "[";
+ if (prettyIndent)
+ s += "\n";
+
+ for (unsigned int i = 0; i < values.size(); i++) {
+ if (prettyIndent)
+ s += indentStr(prettyIndent, indentLevel);
+ s += values[i].write(prettyIndent, indentLevel + 1);
+ if (i != (values.size() - 1))
+ s += ", ";
+ if (prettyIndent)
+ s += "\n";
+ }
+
+ if (prettyIndent)
+ s += indentStr(prettyIndent, indentLevel - 1);
+ s += "]";
+}
+
+void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
+{
+ s += "{";
+ if (prettyIndent)
+ s += "\n";
+
+ for (unsigned int i = 0; i < keys.size(); i++) {
+ if (prettyIndent)
+ s += indentStr(prettyIndent, indentLevel);
+ s += "\"" + json_escape(keys[i]) + "\": ";
+ s += values[i].write(prettyIndent, indentLevel + 1);
+ if (i != (values.size() - 1))
+ s += ",";
+ if (prettyIndent)
+ s += "\n";
+ }
+
+ if (prettyIndent)
+ s += indentStr(prettyIndent, indentLevel - 1);
+ s += "}";
+}
+
diff --git a/src/util.cpp b/src/util.cpp
index 91ac8833d5..ae2145a3a0 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -3,9 +3,14 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
#include "util.h"
#include "chainparamsbase.h"
+#include "random.h"
#include "sync.h"
#include "uint256.h"
#include "version.h"
@@ -16,16 +21,15 @@
#ifndef WIN32
// for posix_fallocate
-#ifdef __linux_
+#ifdef __linux__
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#define _POSIX_C_SOURCE 200112L
-#include <sys/prctl.h>
-#endif
+#endif // __linux__
#include <algorithm>
#include <fcntl.h>
@@ -60,6 +64,10 @@
#include <shlobj.h>
#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
@@ -141,90 +149,6 @@ public:
}
instance_of_cinit;
-
-
-
-
-
-
-
-void RandAddSeed()
-{
- // Seed with CPU performance counter
- int64_t nCounter = GetPerformanceCounter();
- RAND_add(&nCounter, sizeof(nCounter), 1.5);
- memset(&nCounter, 0, sizeof(nCounter));
-}
-
-void RandAddSeedPerfmon()
-{
- RandAddSeed();
-
- // This can take up to 2 seconds, so only do it every 10 minutes
- static int64_t nLastPerfmon;
- if (GetTime() < nLastPerfmon + 10 * 60)
- return;
- nLastPerfmon = GetTime();
-
-#ifdef WIN32
- // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
- // Seed with the entire set of perfmon data
- std::vector <unsigned char> vData(250000,0);
- long ret = 0;
- unsigned long nSize = 0;
- const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
- while (true)
- {
- nSize = vData.size();
- ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
- if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
- break;
- vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially
- }
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- if (ret == ERROR_SUCCESS)
- {
- RAND_add(begin_ptr(vData), nSize, nSize/100.0);
- OPENSSL_cleanse(begin_ptr(vData), nSize);
- LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
- } else {
- static bool warned = false; // Warn only once
- if (!warned)
- {
- LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
- warned = true;
- }
- }
-#endif
-}
-
-uint64_t GetRand(uint64_t nMax)
-{
- if (nMax == 0)
- return 0;
-
- // The range of the random source must be a multiple of the modulus
- // to give every possible output value an equal possibility
- uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
- uint64_t nRand = 0;
- do
- RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
- while (nRand >= nRange);
- return (nRand % nMax);
-}
-
-int GetRandInt(int nMax)
-{
- return GetRand(nMax);
-}
-
-uint256 GetRandHash()
-{
- uint256 hash;
- RAND_bytes((unsigned char*)&hash, sizeof(hash));
- return hash;
-}
-
// LogPrintf() has been broken a couple of times now
// by well-meaning people adding mutexes in the most straightforward way.
// It breaks because it may be called by global destructors during shutdown.
@@ -288,7 +212,7 @@ int LogPrintStr(const std::string &str)
// print to console
ret = fwrite(str.data(), 1, str.size(), stdout);
}
- else if (fPrintToDebugLog)
+ else if (fPrintToDebugLog && AreBaseParamsConfigured())
{
static bool fStartedNewLine = true;
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
@@ -1192,27 +1116,6 @@ void SetMockTime(int64_t nMockTimeIn)
nMockTime = nMockTimeIn;
}
-uint32_t insecure_rand_Rz = 11;
-uint32_t insecure_rand_Rw = 11;
-void seed_insecure_rand(bool fDeterministic)
-{
- //The seed values have some unlikely fixed points which we avoid.
- if(fDeterministic)
- {
- insecure_rand_Rz = insecure_rand_Rw = 11;
- } else {
- uint32_t tmp;
- do {
- RAND_bytes((unsigned char*)&tmp, 4);
- } while(tmp == 0 || tmp == 0x9068ffffU);
- insecure_rand_Rz = tmp;
- do {
- RAND_bytes((unsigned char*)&tmp, 4);
- } while(tmp == 0 || tmp == 0x464fffffU);
- insecure_rand_Rw = tmp;
- }
-}
-
string FormatVersion(int nVersion)
{
if (nVersion%100 == 0)
diff --git a/src/util.h b/src/util.h
index 60db71bfd0..db2005337b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -90,8 +90,6 @@ inline void MilliSleep(int64_t n)
#endif
}
-
-
extern std::map<std::string, std::string> mapArgs;
extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
extern bool fDebug;
@@ -103,8 +101,6 @@ extern bool fLogTimestamps;
extern bool fLogIPs;
extern volatile bool fReopenDebugLog;
-void RandAddSeed();
-void RandAddSeedPerfmon();
void SetupEnvironment();
/* Return true if log accepts specified category */
@@ -187,23 +183,12 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
boost::filesystem::path GetTempPath();
void ShrinkDebugFile();
-int GetRandInt(int nMax);
-uint64_t GetRand(uint64_t nMax);
-uint256 GetRandHash();
int64_t GetTime();
void SetMockTime(int64_t nMockTimeIn);
std::string FormatFullVersion();
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
void runCommand(std::string strCommand);
-
-
-
-
-
-
-
-
inline std::string i64tostr(int64_t n)
{
return strprintf("%d", n);
@@ -289,19 +274,6 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
*/
std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
-inline int64_t GetPerformanceCounter()
-{
- int64_t nCounter = 0;
-#ifdef WIN32
- QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
-#else
- timeval t;
- gettimeofday(&t, NULL);
- nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec;
-#endif
- return nCounter;
-}
-
inline int64_t GetTimeMillis()
{
return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
@@ -371,28 +343,6 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue);
bool SoftSetBoolArg(const std::string& strArg, bool fValue);
/**
- * MWC RNG of George Marsaglia
- * This is intended to be fast. It has a period of 2^59.3, though the
- * least significant 16 bits only have a period of about 2^30.1.
- *
- * @return random value
- */
-extern uint32_t insecure_rand_Rz;
-extern uint32_t insecure_rand_Rw;
-static inline uint32_t insecure_rand(void)
-{
- insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
- insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
- return (insecure_rand_Rw << 16) + insecure_rand_Rz;
-}
-
-/**
- * Seed insecure_rand using the random pool.
- * @param Deterministic Use a determinstic seed
- */
-void seed_insecure_rand(bool fDeterministic=false);
-
-/**
* Timing-attack-resistant comparison.
* Takes time proportional to length
* of first argument.
diff --git a/src/version.h b/src/version.h
index 3d1abacb94..85c5dbf8d7 100644
--- a/src/version.h
+++ b/src/version.h
@@ -28,7 +28,7 @@ extern const std::string CLIENT_DATE;
static const int PROTOCOL_VERSION = 70002;
-// intial proto version, to be increased after version/verack negotiation
+// initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
// disconnect from peers older than this proto version
@@ -45,7 +45,7 @@ static const int NOBLKS_VERSION_END = 32400;
// BIP 0031, pong message, is enabled for all versions AFTER this one
static const int BIP0031_VERSION = 60000;
-// "mempool" command, enhanced "getdata" behavior starts with this version:
+// "mempool" command, enhanced "getdata" behavior starts with this version
static const int MEMPOOL_GD_VERSION = 60002;
#endif
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 8fdc5f4b20..7c04743c0f 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -12,7 +12,6 @@
#include "timedata.h"
#include <boost/algorithm/string/replace.hpp>
-#include <openssl/rand.h>
using namespace std;
@@ -275,7 +274,7 @@ bool CWallet::SetMaxVersion(int nVersion)
return true;
}
-set<uint256> CWallet::GetConflicts(const uint256& txid, bool includeEquivalent) const
+set<uint256> CWallet::GetConflicts(const uint256& txid) const
{
set<uint256> result;
AssertLockHeld(cs_wallet);
@@ -293,8 +292,7 @@ set<uint256> CWallet::GetConflicts(const uint256& txid, bool includeEquivalent)
continue; // No conflict if zero or one spends
range = mapTxSpends.equal_range(txin.prevout);
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
- if (includeEquivalent || !wtx.IsEquivalentTo(mapWallet.at(it->second)))
- result.insert(it->second);
+ result.insert(it->second);
}
return result;
}
@@ -323,7 +321,6 @@ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
const uint256& hash = it->second;
CWalletTx* copyTo = &mapWallet[hash];
if (copyFrom == copyTo) continue;
- if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
copyTo->mapValue = copyFrom->mapValue;
copyTo->vOrderForm = copyFrom->vOrderForm;
// fTimeReceivedIsTxTime not copied on purpose
@@ -384,13 +381,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
RandAddSeedPerfmon();
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
- RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
+ if (!GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE))
+ return false;
CMasterKey kMasterKey;
-
RandAddSeedPerfmon();
+
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
- RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
+ if (!GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE))
+ return false;
CCrypter crypter;
int64_t nStartTime = GetTimeMillis();
@@ -609,28 +608,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
- // Notifications for existing transactions that now have conflicts with this one
- if (fInsertedNew)
- {
- BOOST_FOREACH(const uint256& conflictHash, wtxIn.GetConflicts(false))
- {
- CWalletTx& txConflict = mapWallet[conflictHash];
- NotifyTransactionChanged(this, conflictHash, CT_UPDATED); //Updates UI table
- if (IsFromMe(txConflict) || IsMine(txConflict))
- {
- NotifyTransactionChanged(this, conflictHash, CT_GOT_CONFLICT); //Throws dialog
- // external respend notify
- std::string strCmd = GetArg("-respendnotify", "");
- if (!strCmd.empty())
- {
- boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
- boost::replace_all(strCmd, "%t", conflictHash.GetHex());
- boost::thread t(runCommand, strCmd); // thread runs free
- }
- }
- }
- }
-
// notify an external script when a wallet transaction comes in or is updated
std::string strCmd = GetArg("-walletnotify", "");
@@ -653,12 +630,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
AssertLockHeld(cs_wallet);
bool fExisted = mapWallet.count(tx.GetHash());
if (fExisted && !fUpdate) return false;
-
- bool fIsConflicting = IsConflicting(tx);
- if (fIsConflicting)
- nConflictsReceived++;
-
- if (fExisted || IsMine(tx) || IsFromMe(tx) || fIsConflicting)
+ if (fExisted || IsMine(tx) || IsFromMe(tx))
{
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
@@ -797,8 +769,8 @@ int CWalletTx::GetRequestCount() const
return nRequests;
}
-void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
- list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const
+void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
+ list<COutputEntry>& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const
{
nFee = 0;
listReceived.clear();
@@ -814,10 +786,10 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
}
// Sent/received.
- BOOST_FOREACH(const CTxOut& txout, vout)
+ for (unsigned int i = 0; i < vout.size(); ++i)
{
+ const CTxOut& txout = vout[i];
isminetype fIsMine = pwallet->IsMine(txout);
-
// Only need to handle txouts if AT LEAST one of these is true:
// 1) they debit from us (sent)
// 2) the output is to us (received)
@@ -839,13 +811,15 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
address = CNoDestination();
}
+ COutputEntry output = {address, txout.nValue, (int)i};
+
// If we are debited by the transaction, add the output as a "sent" entry
if (nDebit > 0)
- listSent.push_back(make_pair(address, txout.nValue));
+ listSent.push_back(output);
// If we are receiving the output, add it as a "received" entry
- if (fIsMine)
- listReceived.push_back(make_pair(address, txout.nValue));
+ if (fIsMine & filter)
+ listReceived.push_back(output);
}
}
@@ -857,29 +831,29 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
int64_t allFee;
string strSentAccount;
- list<pair<CTxDestination, int64_t> > listReceived;
- list<pair<CTxDestination, int64_t> > listSent;
+ list<COutputEntry> listReceived;
+ list<COutputEntry> listSent;
GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
if (strAccount == strSentAccount)
{
- BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& s, listSent)
- nSent += s.second;
+ BOOST_FOREACH(const COutputEntry& s, listSent)
+ nSent += s.amount;
nFee = allFee;
}
{
LOCK(pwallet->cs_wallet);
- BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived)
+ BOOST_FOREACH(const COutputEntry& r, listReceived)
{
- if (pwallet->mapAddressBook.count(r.first))
+ if (pwallet->mapAddressBook.count(r.destination))
{
- map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
+ map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
- nReceived += r.second;
+ nReceived += r.amount;
}
else if (strAccount.empty())
{
- nReceived += r.second;
+ nReceived += r.amount;
}
}
}
@@ -945,7 +919,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx.GetDepthInMainChain();
- if (!wtx.IsCoinBase() && nDepth < 0 && (IsMine(wtx) || IsFromMe(wtx)))
+ if (!wtx.IsCoinBase() && nDepth < 0)
{
// Try to add to memory pool
LOCK(mempool.cs);
@@ -965,13 +939,13 @@ void CWalletTx::RelayWalletTransaction()
}
}
-set<uint256> CWalletTx::GetConflicts(bool includeEquivalent) const
+set<uint256> CWalletTx::GetConflicts() const
{
set<uint256> result;
if (pwallet != NULL)
{
uint256 myHash = GetHash();
- result = pwallet->GetConflicts(myHash, includeEquivalent);
+ result = pwallet->GetConflicts(myHash);
result.erase(myHash);
}
return result;
@@ -1075,7 +1049,7 @@ int64_t CWallet::GetWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -1091,7 +1065,7 @@ int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
@@ -1106,7 +1080,7 @@ int64_t CWallet::GetImmatureWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
diff --git a/src/wallet.h b/src/wallet.h
index ab9550a984..73fcfa24e0 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -144,9 +144,6 @@ public:
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID;
- // Increment to cause UI refresh, similar to new block
- int64_t nConflictsReceived;
-
CWallet()
{
SetNull();
@@ -169,7 +166,6 @@ public:
nNextResend = 0;
nLastResend = 0;
nTimeFirstKey = 0;
- nConflictsReceived = 0;
}
std::map<uint256, CWalletTx> mapWallet;
@@ -322,13 +318,6 @@ public:
{
return (GetDebit(tx, ISMINE_ALL) > 0);
}
- bool IsConflicting(const CTransaction& tx) const
- {
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- if (mapTxSpends.count(txin.prevout))
- return true;
- return false;
- }
int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const
{
int64_t nDebit = 0;
@@ -401,7 +390,7 @@ public:
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
// Get wallet transactions that conflict with given transaction (spend same outputs)
- std::set<uint256> GetConflicts(const uint256& txid, bool includeEquivalent) const;
+ std::set<uint256> GetConflicts(const uint256& txid) const;
/** Address book entry changed.
* @note called with lock cs_wallet held.
@@ -467,6 +456,12 @@ static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
mapValue["n"] = i64tostr(nOrderPos);
}
+struct COutputEntry
+{
+ CTxDestination destination;
+ int64_t amount;
+ int vout;
+};
/** A transaction with a bunch of additional info that only the owner cares about.
* It includes any unrecorded transactions needed to link it back to the block chain.
@@ -761,8 +756,8 @@ public:
return nChangeCached;
}
- void GetAmounts(std::list<std::pair<CTxDestination, int64_t> >& listReceived,
- std::list<std::pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const;
+ void GetAmounts(std::list<COutputEntry>& listReceived,
+ std::list<COutputEntry>& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const;
void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived,
int64_t& nSent, int64_t& nFee, const isminefilter& filter) const;
@@ -806,7 +801,7 @@ public:
void RelayWalletTransaction();
- std::set<uint256> GetConflicts(bool includeEquivalent=true) const;
+ std::set<uint256> GetConflicts() const;
};