aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.qt.include1
-rw-r--r--src/bitcoin-cli.cpp182
-rw-r--r--src/bitcoind.cpp31
-rw-r--r--src/chainparams.cpp1
-rw-r--r--src/init.cpp13
-rw-r--r--src/init.h3
-rw-r--r--src/main.cpp13
-rw-r--r--src/net.cpp18
-rw-r--r--src/net.h13
-rw-r--r--src/qt/bitcoin.cpp4
-rw-r--r--src/qt/bitcoingui.cpp5
-rw-r--r--src/qt/forms/aboutdialog.ui192
-rw-r--r--src/qt/forms/helpmessagedialog.ui7
-rw-r--r--src/qt/utilitydialog.cpp116
-rw-r--r--src/qt/utilitydialog.h25
-rw-r--r--src/rpcclient.cpp175
-rw-r--r--src/rpcclient.h10
-rw-r--r--src/test/util_tests.cpp11
-rw-r--r--src/util.cpp55
-rw-r--r--src/util.h5
-rw-r--r--src/version.cpp2
-rw-r--r--src/wallet.cpp16
-rw-r--r--src/wallet.h2
24 files changed, 366 insertions, 535 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3016be47b9..0a76829197 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -171,7 +171,6 @@ nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h
# bitcoind binary #
bitcoind_LDADD = \
libbitcoin_server.a \
- libbitcoin_cli.a \
libbitcoin_common.a \
$(LIBLEVELDB) \
$(LIBMEMENV)
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 72c7486258..647434e1ef 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -76,7 +76,6 @@ QT_TS = \
qt/locale/bitcoin_zh_TW.ts
QT_FORMS_UI = \
- qt/forms/aboutdialog.ui \
qt/forms/addressbookpage.ui \
qt/forms/askpassphrasedialog.ui \
qt/forms/coincontroldialog.ui \
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 29efdfa821..c7327fd7c9 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -12,6 +12,32 @@
#include <boost/filesystem/operations.hpp>
+using namespace boost;
+using namespace boost::asio;
+using namespace json_spirit;
+
+std::string HelpMessageCli()
+{
+ string strUsage;
+ strUsage += _("Options:") + "\n";
+ strUsage += " -? " + _("This help message") + "\n";
+ strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
+ strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
+ strUsage += " -testnet " + _("Use the test network") + "\n";
+ strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
+ "solved instantly. This is intended for regression testing tools and app development.") + "\n";
+ strUsage += " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
+ strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n";
+ strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
+ strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
+ strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
+
+ strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
+ strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
+
+ return strUsage;
+}
+
//////////////////////////////////////////////////////////////////////////////
//
// Start
@@ -39,16 +65,18 @@ static bool AppInitRPC(int argc, char* argv[])
return false;
}
- if (argc<2 || mapArgs.count("-?") || mapArgs.count("--help"))
+ if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
{
- // First part of help message is specific to RPC client
- std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n\n" +
- _("Usage:") + "\n" +
- " bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
- " bitcoin-cli [options] help " + _("List commands") + "\n" +
- " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
+ std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
+ 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" +
+ " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
- strUsage += "\n" + HelpMessageCli(true);
+ strUsage += "\n" + HelpMessageCli();
+ }
fprintf(stdout, "%s", strUsage.c_str());
return false;
@@ -56,6 +84,136 @@ static bool AppInitRPC(int argc, char* argv[])
return true;
}
+Object CallRPC(const string& strMethod, const Array& params)
+{
+ if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
+ throw runtime_error(strprintf(
+ _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
+ "If the file does not exist, create it with owner-readable-only file permissions."),
+ GetConfigFile().string().c_str()));
+
+ // Connect to localhost
+ bool fUseSSL = GetBoolArg("-rpcssl", false);
+ asio::io_service io_service;
+ ssl::context context(io_service, ssl::context::sslv23);
+ context.set_options(ssl::context::no_sslv2);
+ asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
+ SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
+ iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
+
+ bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
+ do {
+ bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort())));
+ if (fConnected) break;
+ if (fWait)
+ MilliSleep(1000);
+ else
+ throw runtime_error("couldn't connect to server");
+ } while (fWait);
+
+ // HTTP basic authentication
+ string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
+ map<string, string> mapRequestHeaders;
+ mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
+
+ // Send request
+ string strRequest = JSONRPCRequest(strMethod, params, 1);
+ string strPost = HTTPPost(strRequest, mapRequestHeaders);
+ stream << strPost << std::flush;
+
+ // Receive HTTP reply status
+ int nProto = 0;
+ int nStatus = ReadHTTPStatus(stream, nProto);
+
+ // Receive HTTP reply message headers and body
+ map<string, string> mapHeaders;
+ string strReply;
+ ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
+
+ if (nStatus == HTTP_UNAUTHORIZED)
+ throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
+ else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
+ throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
+ else if (strReply.empty())
+ throw runtime_error("no response from server");
+
+ // Parse reply
+ Value valReply;
+ if (!read_string(strReply, valReply))
+ throw runtime_error("couldn't parse reply from server");
+ const Object& reply = valReply.get_obj();
+ if (reply.empty())
+ throw runtime_error("expected reply to have result, error and id properties");
+
+ return reply;
+}
+
+int CommandLineRPC(int argc, char *argv[])
+{
+ string strPrint;
+ int nRet = 0;
+ try
+ {
+ // Skip switches
+ while (argc > 1 && IsSwitchChar(argv[1][0]))
+ {
+ argc--;
+ argv++;
+ }
+
+ // Method
+ if (argc < 2)
+ throw runtime_error("too few parameters");
+ string strMethod = argv[1];
+
+ // Parameters default to strings
+ std::vector<std::string> strParams(&argv[2], &argv[argc]);
+ Array params = RPCConvertValues(strMethod, strParams);
+
+ // Execute
+ Object reply = CallRPC(strMethod, params);
+
+ // Parse reply
+ const Value& result = find_value(reply, "result");
+ const Value& error = find_value(reply, "error");
+
+ 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
+ {
+ // Result
+ if (result.type() == null_type)
+ strPrint = "";
+ else if (result.type() == str_type)
+ strPrint = result.get_str();
+ else
+ strPrint = write_string(result, true);
+ }
+ }
+ catch (boost::thread_interrupted) {
+ throw;
+ }
+ catch (std::exception& e) {
+ strPrint = string("error: ") + e.what();
+ nRet = EXIT_FAILURE;
+ }
+ catch (...) {
+ PrintExceptionContinue(NULL, "CommandLineRPC()");
+ throw;
+ }
+
+ if (strPrint != "")
+ {
+ fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
+ }
+ return nRet;
+}
+
int main(int argc, char* argv[])
{
SetupEnvironment();
@@ -63,17 +221,17 @@ int main(int argc, char* argv[])
try
{
if(!AppInitRPC(argc, argv))
- return abs(RPC_MISC_ERROR);
+ return EXIT_FAILURE;
}
catch (std::exception& e) {
PrintExceptionContinue(&e, "AppInitRPC()");
- return abs(RPC_MISC_ERROR);
+ return EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "AppInitRPC()");
- return abs(RPC_MISC_ERROR);
+ return EXIT_FAILURE;
}
- int ret = abs(RPC_MISC_ERROR);
+ int ret = EXIT_FAILURE;
try
{
ret = CommandLineRPC(argc, argv);
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 704332c39b..880955481b 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -4,7 +4,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "rpcserver.h"
-#include "rpcclient.h"
#include "init.h"
#include "main.h"
#include "noui.h"
@@ -83,19 +82,21 @@ bool AppInit(int argc, char* argv[])
return false;
}
- if (mapArgs.count("-?") || mapArgs.count("--help"))
+ if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
{
- // First part of help message is specific to bitcoind / RPC client
- std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" +
- _("Usage:") + "\n" +
- " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" +
- _("Usage (deprecated, use bitcoin-cli):") + "\n" +
- " bitcoind [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
- " bitcoind [options] help " + _("List commands") + "\n" +
- " bitcoind [options] help <command> " + _("Get help for a command") + "\n";
-
- strUsage += "\n" + HelpMessage(HMM_BITCOIND);
- strUsage += "\n" + HelpMessageCli(false);
+ std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
+
+ if (mapArgs.count("-version"))
+ {
+ strUsage += LicenseInfo();
+ }
+ else
+ {
+ strUsage += "\n" + _("Usage:") + "\n" +
+ " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n";
+
+ strUsage += "\n" + HelpMessage(HMM_BITCOIND);
+ }
fprintf(stdout, "%s", strUsage.c_str());
return false;
@@ -109,8 +110,8 @@ bool AppInit(int argc, char* argv[])
if (fCommandLine)
{
- int ret = CommandLineRPC(argc, argv);
- exit(ret);
+ fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
+ exit(1);
}
#ifndef WIN32
fDaemon = GetBoolArg("-daemon", false);
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 3f4d7f7064..1749dd6ff9 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -212,6 +212,7 @@ public:
vFixedSeeds.clear();
vSeeds.clear();
+ vSeeds.push_back(CDNSSeedData("alexykot.me", "testnet-seed.alexykot.me"));
vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"));
vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
diff --git a/src/init.cpp b/src/init.cpp
index 528c3df064..39453da9c8 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -195,7 +195,6 @@ bool static Bind(const CService &addr, unsigned int flags) {
return true;
}
-// Core-specific options shared between UI, daemon and RPC client
std::string HelpMessage(HelpMessageMode hmm)
{
string strUsage = _("Options:") + "\n";
@@ -330,6 +329,18 @@ std::string HelpMessage(HelpMessageMode hmm)
return strUsage;
}
+std::string LicenseInfo()
+{
+ return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
+ "\n" +
+ FormatParagraph(_("This is experimental software.")) + "\n" +
+ "\n" +
+ FormatParagraph(_("Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
+ "\n" +
+ FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.")) +
+ "\n";
+}
+
struct CImportingNow
{
CImportingNow() {
diff --git a/src/init.h b/src/init.h
index 4a967bea37..52daa47616 100644
--- a/src/init.h
+++ b/src/init.h
@@ -28,6 +28,9 @@ enum HelpMessageMode
HMM_BITCOIN_QT
};
+/** Help for options shared between UI and daemon (for -help) */
std::string HelpMessage(HelpMessageMode mode);
+/** Returns licensing information (for -version) */
+std::string LicenseInfo();
#endif
diff --git a/src/main.cpp b/src/main.cpp
index f53d20fbb4..98e1741954 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4293,8 +4293,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// RPC ping request by user
pingSend = true;
}
- if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) {
- // Ping automatically sent as a keepalive
+ if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
+ // Ping automatically sent as a latency probe & keepalive.
pingSend = true;
}
if (pingSend) {
@@ -4302,15 +4302,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
while (nonce == 0) {
RAND_bytes((unsigned char*)&nonce, sizeof(nonce));
}
- pto->nPingNonceSent = nonce;
pto->fPingQueued = false;
+ pto->nPingUsecStart = GetTimeMicros();
if (pto->nVersion > BIP0031_VERSION) {
- // Take timestamp as close as possible before transmitting ping
- pto->nPingUsecStart = GetTimeMicros();
+ pto->nPingNonceSent = nonce;
pto->PushMessage("ping", nonce);
} else {
- // Peer is too old to support ping command with nonce, pong will never arrive, disable timing
- pto->nPingUsecStart = 0;
+ // Peer is too old to support ping command with nonce, pong will never arrive.
+ pto->nPingNonceSent = 0;
pto->PushMessage("ping");
}
}
diff --git a/src/net.cpp b/src/net.cpp
index ac0da26de9..757a06aaed 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1024,23 +1024,27 @@ void ThreadSocketHandler()
//
// Inactivity checking
//
- if (pnode->vSendMsg.empty())
- pnode->nLastSendEmpty = GetTime();
- if (GetTime() - pnode->nTimeConnected > 60)
+ int64_t nTime = GetTime();
+ if (nTime - pnode->nTimeConnected > 60)
{
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
pnode->fDisconnect = true;
}
- else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
+ else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
{
- LogPrintf("socket not sending\n");
+ LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
pnode->fDisconnect = true;
}
- else if (GetTime() - pnode->nLastRecv > 90*60)
+ else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
{
- LogPrintf("socket inactivity timeout\n");
+ LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
+ pnode->fDisconnect = true;
+ }
+ else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
+ {
+ LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
pnode->fDisconnect = true;
}
}
diff --git a/src/net.h b/src/net.h
index f1ac888f5b..14d578a72a 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,6 +28,7 @@
#include <boost/signals2/signal.hpp>
#include <openssl/rand.h>
+
class CAddrMan;
class CBlockIndex;
class CNode;
@@ -36,6 +37,10 @@ namespace boost {
class thread_group;
}
+/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
+static const int PING_INTERVAL = 2 * 60;
+/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
+static const int TIMEOUT_INTERVAL = 20 * 60;
/** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000;
/** -listen default */
@@ -219,7 +224,6 @@ public:
int64_t nLastSend;
int64_t nLastRecv;
- int64_t nLastSendEmpty;
int64_t nTimeConnected;
CAddress addr;
std::string addrName;
@@ -275,10 +279,14 @@ public:
CCriticalSection cs_inventory;
std::multimap<int64_t, CInv> mapAskFor;
- // Ping time measurement
+ // Ping time measurement:
+ // The pong reply we're expecting, or 0 if no pong expected.
uint64_t nPingNonceSent;
+ // Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
int64_t nPingUsecStart;
+ // Last measured round-trip time.
int64_t nPingUsecTime;
+ // Whether a ping is requested.
bool fPingQueued;
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
@@ -290,7 +298,6 @@ public:
nLastRecv = 0;
nSendBytes = 0;
nRecvBytes = 0;
- nLastSendEmpty = GetTime();
nTimeConnected = GetTime();
addr = addrIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 2be8191eb5..387f6ede4b 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -503,9 +503,9 @@ int main(int argc, char *argv[])
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
// but before showing splash screen.
- if (mapArgs.count("-?") || mapArgs.count("--help"))
+ if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
{
- HelpMessageDialog help(NULL);
+ HelpMessageDialog help(NULL, mapArgs.count("-version"));
help.showOrPrint();
return 1;
}
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 3469f990ac..30f5ec8939 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -549,14 +549,13 @@ void BitcoinGUI::aboutClicked()
if(!clientModel)
return;
- AboutDialog dlg(this);
- dlg.setModel(clientModel);
+ HelpMessageDialog dlg(this, true);
dlg.exec();
}
void BitcoinGUI::showHelpMessageClicked()
{
- HelpMessageDialog *help = new HelpMessageDialog(this);
+ HelpMessageDialog *help = new HelpMessageDialog(this, false);
help->setAttribute(Qt::WA_DeleteOnClose);
help->show();
}
diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui
deleted file mode 100644
index fec63f737a..0000000000
--- a/src/qt/forms/aboutdialog.ui
+++ /dev/null
@@ -1,192 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AboutDialog</class>
- <widget class="QDialog" name="AboutDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>593</width>
- <height>319</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>About Bitcoin Core</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="pixmap">
- <pixmap resource="../bitcoin.qrc">:/images/about</pixmap>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="label">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>&lt;b&gt;Bitcoin Core&lt;/b&gt; version</string>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="versionLabel">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string notr="true">0.3.666-beta</string>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <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>
- <widget class="QLabel" name="copyrightLabel">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string notr="true">Copyright &amp;copy; 2009-YYYY The Bitcoin Core developers</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>
-This is experimental software.
-
-Distributed under the MIT/X11 software license, see the accompanying file COPYING or &lt;a href=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;http://www.opensource.org/licenses/mit-license.php&lt;/a&gt;.
-
-This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (&lt;a href=&quot;https://www.openssl.org/&quot;&gt;https://www.openssl.org/&lt;/a&gt;) and cryptographic software written by Eric Young (&lt;a href=&quot;mailto:eay@cryptsoft.com&quot;&gt;eay@cryptsoft.com&lt;/a&gt;) and UPnP software written by Thomas Bernard.</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources>
- <include location="../bitcoin.qrc"/>
- </resources>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>AboutDialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>20</x>
- <y>20</y>
- </hint>
- <hint type="destinationlabel">
- <x>20</x>
- <y>20</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>AboutDialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>20</x>
- <y>20</y>
- </hint>
- <hint type="destinationlabel">
- <x>20</x>
- <y>20</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui
index f68fea7e64..d8ab27c238 100644
--- a/src/qt/forms/helpmessagedialog.ui
+++ b/src/qt/forms/helpmessagedialog.ui
@@ -16,7 +16,7 @@
</font>
</property>
<property name="windowTitle">
- <string>Bitcoin Core - Command-line options</string>
+ <string notr="true">Bitcoin Core - Command-line options</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
@@ -54,11 +54,6 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="helpMessageLabel">
- <property name="font">
- <font>
- <family>Terminal</family>
- </font>
- </property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 01b710e876..eb647d0170 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -4,7 +4,6 @@
#include "utilitydialog.h"
-#include "ui_aboutdialog.h"
#include "ui_helpmessagedialog.h"
#include "bitcoingui.h"
@@ -16,72 +15,64 @@
#include "util.h"
#include <QLabel>
+#include <QRegExp>
#include <QVBoxLayout>
-/** "About" dialog box */
-AboutDialog::AboutDialog(QWidget *parent) :
+/** "Help message" or "About" dialog box */
+HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
QDialog(parent),
- ui(new Ui::AboutDialog)
+ ui(new Ui::HelpMessageDialog)
{
ui->setupUi(this);
+ GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this);
- // Set current copyright year
- ui->copyrightLabel->setText(tr("Copyright") + QString(" &copy; 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers"));
-}
-
-void AboutDialog::setModel(ClientModel *model)
-{
- if(model)
- {
- QString version = model->formatFullVersion();
- /* On x86 add a bit specifier to the version so that users can distinguish between
- * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious.
- */
+ QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion());
+ /* On x86 add a bit specifier to the version so that users can distinguish between
+ * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious.
+ */
#if defined(__x86_64__)
- version += " " + tr("(%1-bit)").arg(64);
+ version += " " + tr("(%1-bit)").arg(64);
#elif defined(__i386__ )
- version += " " + tr("(%1-bit)").arg(32);
+ version += " " + tr("(%1-bit)").arg(32);
#endif
- ui->versionLabel->setText(version);
- }
-}
-
-AboutDialog::~AboutDialog()
-{
- delete ui;
-}
-
-void AboutDialog::on_buttonBox_accepted()
-{
- close();
-}
-
-/** "Help message" dialog box */
-HelpMessageDialog::HelpMessageDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::HelpMessageDialog)
-{
- ui->setupUi(this);
- GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this);
-
- header = tr("Bitcoin Core") + " " + tr("version") + " " +
- QString::fromStdString(FormatFullVersion()) + "\n\n" +
- tr("Usage:") + "\n" +
- " bitcoin-qt [" + tr("command-line options") + "] " + "\n";
-
- coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));
-
- uiOptions = tr("UI options") + ":\n" +
- " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" +
- " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
- " -min " + tr("Start minimized") + "\n" +
- " -rootcertificates=<file> " + tr("Set SSL root certificates for payment request (default: -system-)") + "\n" +
- " -splash " + tr("Show splash screen on startup (default: 1)");
- ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont());
-
- // Set help message text
- ui->helpMessageLabel->setText(header + "\n" + coreOptions + "\n" + uiOptions);
+ if (about)
+ {
+ setWindowTitle(tr("About Bitcoin Core"));
+
+ /// HTML-format the license message from the core
+ QString licenseInfo = QString::fromStdString(LicenseInfo());
+ QString licenseInfoHTML = licenseInfo;
+ // Make URLs clickable
+ QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2);
+ uri.setMinimal(true); // use non-greedy matching
+ licenseInfoHTML.replace(uri, "<a href=\"\\1\">\\1</a>");
+ // Replace newlines with HTML breaks
+ licenseInfoHTML.replace("\n\n", "<br><br>");
+
+ ui->helpMessageLabel->setTextFormat(Qt::RichText);
+ ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ text = version + "\n" + licenseInfo;
+ ui->helpMessageLabel->setText(version + "<br><br>" + licenseInfoHTML);
+ ui->helpMessageLabel->setWordWrap(true);
+ } else {
+ setWindowTitle(tr("Command-line options"));
+ QString header = tr("Usage:") + "\n" +
+ " bitcoin-qt [" + tr("command-line options") + "] " + "\n";
+
+ QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));
+
+ QString uiOptions = tr("UI options") + ":\n" +
+ " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" +
+ " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
+ " -min " + tr("Start minimized") + "\n" +
+ " -rootcertificates=<file> " + tr("Set SSL root certificates for payment request (default: -system-)") + "\n" +
+ " -splash " + tr("Show splash screen on startup (default: 1)");
+
+ ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont());
+ text = version + "\n" + header + "\n" + coreOptions + "\n" + uiOptions;
+ ui->helpMessageLabel->setText(text);
+ }
}
HelpMessageDialog::~HelpMessageDialog()
@@ -93,18 +84,17 @@ HelpMessageDialog::~HelpMessageDialog()
void HelpMessageDialog::printToConsole()
{
// On other operating systems, the expected action is to print the message to the console.
- QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions + "\n";
- fprintf(stdout, "%s", strUsage.toStdString().c_str());
+ fprintf(stdout, "%s\n", qPrintable(text));
}
void HelpMessageDialog::showOrPrint()
{
#if defined(WIN32)
- // On Windows, show a message box, as there is no stderr/stdout in windowed applications
- exec();
+ // On Windows, show a message box, as there is no stderr/stdout in windowed applications
+ exec();
#else
- // On other operating systems, print help text to console
- printToConsole();
+ // On other operating systems, print help text to console
+ printToConsole();
#endif
}
diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h
index 874daf6a7f..154bb70b8b 100644
--- a/src/qt/utilitydialog.h
+++ b/src/qt/utilitydialog.h
@@ -12,35 +12,16 @@ class BitcoinGUI;
class ClientModel;
namespace Ui {
- class AboutDialog;
class HelpMessageDialog;
}
-/** "About" dialog box */
-class AboutDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit AboutDialog(QWidget *parent);
- ~AboutDialog();
-
- void setModel(ClientModel *model);
-
-private:
- Ui::AboutDialog *ui;
-
-private slots:
- void on_buttonBox_accepted();
-};
-
/** "Help message" dialog box */
class HelpMessageDialog : public QDialog
{
Q_OBJECT
public:
- explicit HelpMessageDialog(QWidget *parent);
+ explicit HelpMessageDialog(QWidget *parent, bool about);
~HelpMessageDialog();
void printToConsole();
@@ -48,9 +29,7 @@ public:
private:
Ui::HelpMessageDialog *ui;
- QString header;
- QString coreOptions;
- QString uiOptions;
+ QString text;
private slots:
void on_okButton_accepted();
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index b89a95ad11..3a06e33016 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -12,86 +12,9 @@
#include <stdint.h>
-#include <boost/algorithm/string.hpp>
-#include <boost/asio.hpp>
-#include <boost/asio/ssl.hpp>
-#include <boost/bind.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/foreach.hpp>
-#include <boost/iostreams/concepts.hpp>
-#include <boost/iostreams/stream.hpp>
-#include <boost/shared_ptr.hpp>
-#include "json/json_spirit_writer_template.h"
-
using namespace std;
-using namespace boost;
-using namespace boost::asio;
using namespace json_spirit;
-Object CallRPC(const string& strMethod, const Array& params)
-{
- if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
- throw runtime_error(strprintf(
- _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
- "If the file does not exist, create it with owner-readable-only file permissions."),
- GetConfigFile().string().c_str()));
-
- // Connect to localhost
- bool fUseSSL = GetBoolArg("-rpcssl", false);
- asio::io_service io_service;
- ssl::context context(io_service, ssl::context::sslv23);
- context.set_options(ssl::context::no_sslv2);
- asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
- SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
- iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
-
- bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
- do {
- bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort())));
- if (fConnected) break;
- if (fWait)
- MilliSleep(1000);
- else
- throw runtime_error("couldn't connect to server");
- } while (fWait);
-
- // HTTP basic authentication
- string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
- map<string, string> mapRequestHeaders;
- mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
-
- // Send request
- string strRequest = JSONRPCRequest(strMethod, params, 1);
- string strPost = HTTPPost(strRequest, mapRequestHeaders);
- stream << strPost << std::flush;
-
- // Receive HTTP reply status
- int nProto = 0;
- int nStatus = ReadHTTPStatus(stream, nProto);
-
- // Receive HTTP reply message headers and body
- map<string, string> mapHeaders;
- string strReply;
- ReadHTTPMessage(stream, mapHeaders, strReply, nProto);
-
- if (nStatus == HTTP_UNAUTHORIZED)
- throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
- else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
- throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
- else if (strReply.empty())
- throw runtime_error("no response from server");
-
- // Parse reply
- Value valReply;
- if (!read_string(strReply, valReply))
- throw runtime_error("couldn't parse reply from server");
- const Object& reply = valReply.get_obj();
- if (reply.empty())
- throw runtime_error("expected reply to have result, error and id properties");
-
- return reply;
-}
-
template<typename T>
void ConvertTo(Value& value, bool fAllowNull=false)
{
@@ -182,101 +105,3 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
return params;
}
-int CommandLineRPC(int argc, char *argv[])
-{
- string strPrint;
- int nRet = 0;
- try
- {
- // Skip switches
- while (argc > 1 && IsSwitchChar(argv[1][0]))
- {
- argc--;
- argv++;
- }
-
- // Method
- if (argc < 2)
- throw runtime_error("too few parameters");
- string strMethod = argv[1];
-
- // Parameters default to strings
- std::vector<std::string> strParams(&argv[2], &argv[argc]);
- Array params = RPCConvertValues(strMethod, strParams);
-
- // Execute
- Object reply = CallRPC(strMethod, params);
-
- // Parse reply
- const Value& result = find_value(reply, "result");
- const Value& error = find_value(reply, "error");
-
- 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
- {
- // Result
- if (result.type() == null_type)
- strPrint = "";
- else if (result.type() == str_type)
- strPrint = result.get_str();
- else
- strPrint = write_string(result, true);
- }
- }
- catch (boost::thread_interrupted) {
- throw;
- }
- catch (std::exception& e) {
- strPrint = string("error: ") + e.what();
- nRet = abs(RPC_MISC_ERROR);
- }
- catch (...) {
- PrintExceptionContinue(NULL, "CommandLineRPC()");
- throw;
- }
-
- if (strPrint != "")
- {
- fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
- }
- return nRet;
-}
-
-std::string HelpMessageCli(bool mainProgram)
-{
- string strUsage;
- if(mainProgram)
- {
- strUsage += _("Options:") + "\n";
- strUsage += " -? " + _("This help message") + "\n";
- strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
- strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
- strUsage += " -testnet " + _("Use the test network") + "\n";
- strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
- "solved instantly. This is intended for regression testing tools and app development.") + "\n";
- } else {
- strUsage += _("RPC client options:") + "\n";
- }
-
- strUsage += " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n";
- strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n";
- strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
-
- if(mainProgram)
- {
- strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
- strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
-
- strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
- strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
- }
-
- return strUsage;
-}
-
diff --git a/src/rpcclient.h b/src/rpcclient.h
index e101d22ec5..840890e34b 100644
--- a/src/rpcclient.h
+++ b/src/rpcclient.h
@@ -10,16 +10,6 @@
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
-int CommandLineRPC(int argc, char *argv[]);
-
json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams);
-/** Show help message for bitcoin-cli.
- * The mainProgram argument is used to determine whether to show this message as main program
- * (and include some common options) or as sub-header of another help message.
- *
- * @note the argument can be removed once bitcoin-cli functionality is removed from bitcoind
- */
-std::string HelpMessageCli(bool mainProgram);
-
#endif
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 0e53a57593..0b071361d8 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -351,4 +351,15 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(!ParseInt32("32482348723847471234", NULL));
}
+BOOST_AUTO_TEST_CASE(test_FormatParagraph)
+{
+ BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
+ BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
+ BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), "test");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
+ BOOST_CHECK_EQUAL(FormatParagraph("testerde test ", 4, 0), "testerde\ntest");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test");
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/util.cpp b/src/util.cpp
index cccf2df484..30590912ff 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -460,6 +460,7 @@ void ParseParameters(int argc, const char* const argv[])
{
mapArgs.clear();
mapMultiArgs.clear();
+
for (int i = 1; i < argc; i++)
{
std::string str(argv[i]);
@@ -475,9 +476,15 @@ void ParseParameters(int argc, const char* const argv[])
if (boost::algorithm::starts_with(str, "/"))
str = "-" + str.substr(1);
#endif
+
if (str[0] != '-')
break;
+ // Interpret --foo as -foo.
+ // If both --foo and -foo are set, the last takes effect.
+ if (str.length() > 1 && str[1] == '-')
+ str = str.substr(1);
+
mapArgs[str] = strValue;
mapMultiArgs[str].push_back(strValue);
}
@@ -485,19 +492,8 @@ void ParseParameters(int argc, const char* const argv[])
// New 0.6 features:
BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
{
- string name = entry.first;
-
- // interpret --foo as -foo (as long as both are not set)
- if (name.find("--") == 0)
- {
- std::string singleDash(name.begin()+1, name.end());
- if (mapArgs.count(singleDash) == 0)
- mapArgs[singleDash] = entry.second;
- name = singleDash;
- }
-
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
- InterpretNegativeSetting(name, mapArgs);
+ InterpretNegativeSetting(entry.first, mapArgs);
}
}
@@ -1407,3 +1403,38 @@ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
ss << boost::posix_time::from_time_t(nTime);
return ss.str();
}
+
+std::string FormatParagraph(const std::string in, size_t width, size_t indent)
+{
+ std::stringstream out;
+ size_t col = 0;
+ size_t ptr = 0;
+ while(ptr < in.size())
+ {
+ // Find beginning of next word
+ ptr = in.find_first_not_of(' ', ptr);
+ if (ptr == std::string::npos)
+ break;
+ // Find end of next word
+ size_t endword = in.find_first_of(' ', ptr);
+ if (endword == std::string::npos)
+ endword = in.size();
+ // Add newline and indentation if this wraps over the allowed width
+ if (col > 0)
+ {
+ if ((col + endword - ptr) > width)
+ {
+ out << '\n';
+ for(size_t i=0; i<indent; ++i)
+ out << ' ';
+ col = 0;
+ } else
+ out << ' ';
+ }
+ // Append word
+ out << in.substr(ptr, endword - ptr);
+ col += endword - ptr;
+ ptr = endword;
+ }
+ return out.str();
+}
diff --git a/src/util.h b/src/util.h
index e070365790..da1810a3d3 100644
--- a/src/util.h
+++ b/src/util.h
@@ -286,6 +286,11 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
return HexStr(vch.begin(), vch.end(), fSpaces);
}
+/** Format a paragraph of text to a fixed width, adding spaces for
+ * indentation to any added line.
+ */
+std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
+
inline int64_t GetPerformanceCounter()
{
int64_t nCounter = 0;
diff --git a/src/version.cpp b/src/version.cpp
index 51e34aa9c9..d86caa3ac2 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -12,7 +12,7 @@
const std::string CLIENT_NAME("Satoshi");
// Client version number
-#define CLIENT_VERSION_SUFFIX "-beta"
+#define CLIENT_VERSION_SUFFIX ""
// The following part of the code determines the CLIENT_BUILD variable.
diff --git a/src/wallet.cpp b/src/wallet.cpp
index ef0b442e1a..400c966a95 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -128,6 +128,22 @@ bool CWallet::AddCScript(const CScript& redeemScript)
return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
}
+bool CWallet::LoadCScript(const CScript& redeemScript)
+{
+ /* A sanity check was added in pull #3843 to avoid adding redeemScripts
+ * that never can be redeemed. However, old wallets may still contain
+ * these. Do not add them to the wallet and warn. */
+ if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
+ {
+ std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString();
+ LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
+ __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
+ return true;
+ }
+
+ return CCryptoKeyStore::AddCScript(redeemScript);
+}
+
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
CCrypter crypter;
diff --git a/src/wallet.h b/src/wallet.h
index 274c31157c..7df656fc25 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -211,7 +211,7 @@ public:
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
bool AddCScript(const CScript& redeemScript);
- bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
+ bool LoadCScript(const CScript& redeemScript);
/// Adds a destination data tuple to the store, and saves it to disk
bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);