diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/init.cpp | 346 | ||||
-rw-r--r-- | src/init.h | 3 | ||||
-rw-r--r-- | src/irc.cpp | 5 | ||||
-rw-r--r-- | src/net.cpp | 14 | ||||
-rw-r--r-- | src/net.h | 1 | ||||
-rw-r--r-- | src/netbase.cpp | 14 | ||||
-rw-r--r-- | src/qt/addressbookpage.cpp | 1 | ||||
-rw-r--r-- | src/qt/bitcoin.cpp | 58 | ||||
-rw-r--r-- | src/qt/bitcoingui.cpp | 13 | ||||
-rw-r--r-- | src/qt/bitcoingui.h | 3 | ||||
-rw-r--r-- | src/qt/forms/verifymessagedialog.ui | 149 | ||||
-rw-r--r-- | src/qt/guiutil.cpp | 2 | ||||
-rw-r--r-- | src/qt/qrcodedialog.cpp | 1 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 9 | ||||
-rw-r--r-- | src/qt/rpcconsole.h | 3 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 10 | ||||
-rw-r--r-- | src/qt/verifymessagedialog.cpp | 75 | ||||
-rw-r--r-- | src/qt/verifymessagedialog.h | 36 |
18 files changed, 559 insertions, 184 deletions
diff --git a/src/init.cpp b/src/init.cpp index 38e2b6f9e6..9b12ab0aa4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -100,14 +100,52 @@ int main(int argc, char* argv[]) return 1; } -#endif bool AppInit(int argc, char* argv[]) { bool fRet = false; try { - fRet = AppInit2(argc, argv); + // + // Parameters + // + // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() + ParseParameters(argc, argv); + if (!boost::filesystem::is_directory(GetDataDir(false))) + { + fprintf(stderr, "Error: Specified directory does not exist\n"); + Shutdown(NULL); + } + ReadConfigFile(mapArgs, mapMultiArgs); + + if (mapArgs.count("-?") || mapArgs.count("--help")) + { + // First part of help message is specific to bitcoind / RPC client + std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" + + _("Usage:") + "\n" + + " bitcoind [options] " + "\n" + + " bitcoind [options] <command> [params] " + _("Send command to -server or bitcoind") + "\n" + + " bitcoind [options] help " + _("List commands") + "\n" + + " bitcoind [options] help <command> " + _("Get help for a command") + "\n"; + + strUsage += "\n" + HelpMessage(); + + fprintf(stderr, "%s", strUsage.c_str()); + return false; + } + + // Command-line RPC + for (int i = 1; i < argc; i++) + if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)) + fCommandLine = true; + + if (fCommandLine) + { + int ret = CommandLineRPC(argc, argv); + exit(ret); + } + + fRet = AppInit2(); } catch (std::exception& e) { PrintException(&e, "AppInit()"); @@ -118,20 +156,114 @@ bool AppInit(int argc, char* argv[]) Shutdown(NULL); return fRet; } +#endif + +bool static InitError(const std::string &str) +{ + ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxMODAL); + return false; + +} + +bool static InitWarning(const std::string &str) +{ + ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL); + return true; +} + bool static Bind(const CService &addr) { if (IsLimited(addr)) return false; std::string strError; if (!BindListenPort(addr, strError)) - { - ThreadSafeMessageBox(strError, _("Bitcoin"), wxOK | wxMODAL); - return false; - } + return InitError(strError); return true; } -bool AppInit2(int argc, char* argv[]) +// Core-specific options shared between UI and daemon +std::string HelpMessage() +{ + string strUsage = _("Options:") + "\n" + + " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n" + + " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n" + + " -gen " + _("Generate coins") + "\n" + + " -gen=0 " + _("Don't generate coins") + "\n" + + " -datadir=<dir> " + _("Specify data directory") + "\n" + + " -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" + + " -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" + + " -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" + + " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" + + " -socks=<n> " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" + + " -noproxy=<net> " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" + + " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + + " -proxydns " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" + + " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" + + " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" + + " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + + " -connect=<ip> " + _("Connect only to the specified node") + "\n" + + " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + + " -externalip=<ip> " + _("Specify your own public address") + "\n" + + " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4 or IPv6)") + "\n" + + " -discover " + _("Try to discover public IP address (default: 1)") + "\n" + + " -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" + + " -listen " + _("Accept connections from outside (default: 1)") + "\n" + + " -bind=<addr> " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + + " -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" + + " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + + " -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + + " -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" + + " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" + +#ifdef USE_UPNP +#if USE_UPNP + " -upnp " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" + +#else + " -upnp " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" + +#endif +#endif + " -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" + + " -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n" + +#ifdef QT_GUI + " -server " + _("Accept command line and JSON-RPC commands") + "\n" + +#endif +#if !defined(WIN32) && !defined(QT_GUI) + " -daemon " + _("Run in the background as a daemon and accept commands") + "\n" + +#endif + " -testnet " + _("Use the test network") + "\n" + + " -debug " + _("Output extra debugging information") + "\n" + + " -logtimestamps " + _("Prepend debug output with timestamp") + "\n" + + " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n" + +#ifdef WIN32 + " -printtodebugger " + _("Send trace/debug info to debugger") + "\n" + +#endif + " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n" + + " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n" + + " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" + + " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n" + + " -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" + + " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" + + " -upgradewallet " + _("Upgrade wallet to latest format") + "\n" + + " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n" + + " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n" + + " -checkblocks=<n> " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" + + " -checklevel=<n> " + _("How thorough the block verification is (0-6, default: 1)") + "\n" + + " -loadblock=<file> " + _("Imports blocks from external blk000?.dat file") + "\n" + + " -? " + _("This help message") + "\n"; + + strUsage += string() + + _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + + " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + + " -rpcsslcertificatechainfile=<file.cert> " + _("Server certificate file (default: server.cert)") + "\n" + + " -rpcsslprivatekeyfile=<file.pem> " + _("Server private key (default: server.pem)") + "\n" + + " -rpcsslciphers=<ciphers> " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n"; + + return strUsage; +} + +/** Initialize bitcoin. + * @pre Parameters should be parsed and config file should be read. + */ +bool AppInit2() { #ifdef _MSC_VER // Turn off microsoft heap dump noise @@ -156,120 +288,6 @@ bool AppInit2(int argc, char* argv[]) sigaction(SIGHUP, &sa, NULL); #endif - // - // Parameters - // - // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() -#if !defined(QT_GUI) - ParseParameters(argc, argv); - if (!boost::filesystem::is_directory(GetDataDir(false))) - { - fprintf(stderr, "Error: Specified directory does not exist\n"); - Shutdown(NULL); - } - ReadConfigFile(mapArgs, mapMultiArgs); -#endif - - if (mapArgs.count("-?") || mapArgs.count("--help")) - { - string strUsage = string() + - _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" + - _("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" + - " bitcoind [options] \t " + "\n" + - " bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind") + "\n" + - " bitcoind [options] help \t\t " + _("List commands") + "\n" + - " bitcoind [options] help <command> \t\t " + _("Get help for a command") + "\n" + - _("Options:") + "\n" + - " -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)") + "\n" + - " -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)") + "\n" + - " -gen \t\t " + _("Generate coins") + "\n" + - " -gen=0 \t\t " + _("Don't generate coins") + "\n" + - " -min \t\t " + _("Start minimized") + "\n" + - " -splash \t\t " + _("Show splash screen on startup (default: 1)") + "\n" + - " -datadir=<dir> \t\t " + _("Specify data directory") + "\n" + - " -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" + - " -dblogsize=<n> \t\t " + _("Set database disk log size in megabytes (default: 100)") + "\n" + - " -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" + - " -proxy=<ip:port> \t " + _("Connect through socks proxy") + "\n" + - " -socks=<n> \t " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" + - " -noproxy=<net> \t " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" + - " -dns \t " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + - " -proxydns \t " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" + - " -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" + - " -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" + - " -addnode=<ip> \t " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + - " -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" + - " -seednode=<ip> \t\t " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + - " -externalip=<ip> \t " + _("Specify your own public address") + "\n" + - " -blocknet=<net> \t " + _("Do not connect to addresses in network <net> (IPv4 or IPv6)") + "\n" + - " -discover \t " + _("Try to discover public IP address (default: 1)") + "\n" + - " -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" + - " -listen \t " + _("Accept connections from outside (default: 1)") + "\n" + - " -bind=<addr> \t " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + -#ifdef QT_GUI - " -lang=<lang> \t\t " + _("Set language, for example \"de_DE\" (default: system locale)") + "\n" + -#endif - " -dnsseed \t " + _("Find peers using DNS lookup (default: 1)") + "\n" + - " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + - " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" + - " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" + - " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" + -#ifdef USE_UPNP -#if USE_UPNP - " -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" + -#else - " -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" + -#endif - " -detachdb \t " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" + -#endif - " -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send") + "\n" + -#ifdef QT_GUI - " -server \t\t " + _("Accept command line and JSON-RPC commands") + "\n" + -#endif -#if !defined(WIN32) && !defined(QT_GUI) - " -daemon \t\t " + _("Run in the background as a daemon and accept commands") + "\n" + -#endif - " -testnet \t\t " + _("Use the test network") + "\n" + - " -debug \t\t " + _("Output extra debugging information") + "\n" + - " -logtimestamps \t " + _("Prepend debug output with timestamp") + "\n" + - " -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file") + "\n" + -#ifdef WIN32 - " -printtodebugger \t " + _("Send trace/debug info to debugger") + "\n" + -#endif - " -rpcuser=<user> \t " + _("Username for JSON-RPC connections") + "\n" + - " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections") + "\n" + - " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" + - " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address") + "\n" + - " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" + - " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" + - " -upgradewallet \t " + _("Upgrade wallet to latest format") + "\n" + - " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" + - " -rescan \t " + _("Rescan the block chain for missing wallet transactions") + "\n" + - " -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" + - " -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n" + - " -loadblock=<file>\t " + _("Imports blocks from external blk000?.dat file") + "\n"; - - strUsage += string() + - _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + - " -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + - " -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)") + "\n" + - " -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)") + "\n" + - " -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n"; - - strUsage += string() + - " -? \t\t " + _("This help message") + "\n"; - - // Remove tabs - strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end()); -#if defined(QT_GUI) && defined(WIN32) - // On windows, show a message box, as there is no stderr - ThreadSafeMessageBox(strUsage, _("Usage"), wxOK | wxMODAL); -#else - fprintf(stderr, "%s", strUsage.c_str()); -#endif - return false; - } - fTestNet = GetBoolArg("-testnet"); if (fTestNet) { @@ -298,18 +316,6 @@ bool AppInit2(int argc, char* argv[]) fPrintToDebugger = GetBoolArg("-printtodebugger"); fLogTimestamps = GetBoolArg("-logtimestamps"); -#ifndef QT_GUI - for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)) - fCommandLine = true; - - if (fCommandLine) - { - int ret = CommandLineRPC(argc, argv); - exit(ret); - } -#endif - #if !defined(WIN32) && !defined(QT_GUI) if (fDaemon) { @@ -352,10 +358,7 @@ bool AppInit2(int argc, char* argv[]) if (file) fclose(file); static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) - { - ThreadSafeMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str()), _("Bitcoin"), wxOK|wxMODAL); - return false; - } + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str())); std::ostringstream strErrors; // @@ -414,8 +417,7 @@ bool AppInit2(int argc, char* argv[]) { strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n"; printf("%s", strErrors.str().c_str()); - ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL); - return false; + return InitError(strErrors.str()); } else strErrors << _("Error loading wallet.dat") << "\n"; @@ -485,10 +487,7 @@ bool AppInit2(int argc, char* argv[]) printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size()); if (!strErrors.str().empty()) - { - ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL); - return false; - } + return InitError(strErrors.str()); // Add wallet transactions that aren't already in a block to mapTransactions pwalletMain->ReacceptWalletTransactions(); @@ -541,20 +540,15 @@ bool AppInit2(int argc, char* argv[]) fUseProxy = true; addrProxy = CService(mapArgs["-proxy"], 9050); if (!addrProxy.IsValid()) - { - ThreadSafeMessageBox(_("Invalid -proxy address"), _("Bitcoin"), wxOK | wxMODAL); - return false; - } + return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str())); } if (mapArgs.count("-noproxy")) { BOOST_FOREACH(std::string snet, mapMultiArgs["-noproxy"]) { enum Network net = ParseNetwork(snet); - if (net == NET_UNROUTABLE) { - ThreadSafeMessageBox(_("Unknown network specified in -noproxy"), _("Bitcoin"), wxOK | wxMODAL); - return false; - } + if (net == NET_UNROUTABLE) + return InitError(strprintf(_("Unknown network specified in -noproxy: '%s'"), snet.c_str())); SetNoProxy(net); } } @@ -578,14 +572,18 @@ bool AppInit2(int argc, char* argv[]) SoftSetBoolArg("-discover", false); } - if (mapArgs.count("-blocknet")) { - BOOST_FOREACH(std::string snet, mapMultiArgs["-blocknet"]) { + if (mapArgs.count("-onlynet")) { + std::set<enum Network> nets; + BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); - if (net == NET_UNROUTABLE) { - ThreadSafeMessageBox(_("Unknown network specified in -blocknet"), _("Bitcoin"), wxOK | wxMODAL); - return false; - } - SetLimited(net); + if (net == NET_UNROUTABLE) + return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); + nets.insert(net); + } + for (int n = 0; n < NET_MAX; n++) { + enum Network net = (enum Network)n; + if (!nets.count(net)) + SetLimited(net); } } @@ -595,6 +593,8 @@ bool AppInit2(int argc, char* argv[]) fNameLookup = true; fNoListen = !GetBoolArg("-listen", true); nSocksVersion = GetArg("-socks", 5); + if (nSocksVersion != 4 && nSocksVersion != 5) + return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) AddOneShot(strDest); @@ -611,35 +611,41 @@ bool AppInit2(int argc, char* argv[]) std::string strError; if (mapArgs.count("-bind")) { BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { - fBound |= Bind(CService(strBind, GetListenPort(), false)); + CService addrBind; + if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) + return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str())); + fBound |= Bind(addrBind); } } else { struct in_addr inaddr_any; inaddr_any.s_addr = INADDR_ANY; - fBound |= Bind(CService(inaddr_any, GetListenPort())); + if (!IsLimited(NET_IPV4)) + fBound |= Bind(CService(inaddr_any, GetListenPort())); #ifdef USE_IPV6 - fBound |= Bind(CService(in6addr_any, GetListenPort())); + if (!IsLimited(NET_IPV6)) + fBound |= Bind(CService(in6addr_any, GetListenPort())); #endif } if (!fBound) - return false; + return InitError(_("Not listening on any port")); } if (mapArgs.count("-externalip")) { - BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) + BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) { + CService addrLocal(strAddr, GetListenPort(), fNameLookup); + if (!addrLocal.IsValid()) + return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str())); AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); + } } if (mapArgs.count("-paytxfee")) { if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) - { - ThreadSafeMessageBox(_("Invalid amount for -paytxfee=<amount>"), _("Bitcoin"), wxOK | wxMODAL); - return false; - } + return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"].c_str())); if (nTransactionFee > 0.25 * COIN) - ThreadSafeMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL); + InitWarning(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction.")); } // @@ -651,12 +657,14 @@ bool AppInit2(int argc, char* argv[]) RandAddSeedPerfmon(); if (!CreateThread(StartNode, NULL)) - ThreadSafeMessageBox(_("Error: CreateThread(StartNode) failed"), _("Bitcoin"), wxOK | wxMODAL); + InitError(_("Error: could not start node")); if (fServer) CreateThread(ThreadRPCServer, NULL); #if !defined(QT_GUI) + // Loop until process is exit()ed from shutdown() function, + // called from ThreadRPCServer thread when a "stop" command is received. while (1) Sleep(5000); #endif diff --git a/src/init.h b/src/init.h index 0a2f0d8932..9a8f98cce9 100644 --- a/src/init.h +++ b/src/init.h @@ -11,6 +11,7 @@ extern CWallet* pwalletMain; void Shutdown(void* parg); bool AppInit(int argc, char* argv[]); -bool AppInit2(int argc, char* argv[]); +bool AppInit2(); +std::string HelpMessage(); #endif diff --git a/src/irc.cpp b/src/irc.cpp index 525bd7a8da..4baffedb54 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -246,11 +246,12 @@ void ThreadIRCSeed2(void* parg) return; } + CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses CService addrLocal; string strMyName; - if (GetLocal(addrLocal, &addrConnect)) + if (GetLocal(addrLocal, &addrIPv4)) strMyName = EncodeAddress(GetLocalAddress(&addrConnect)); - else + if (strMyName == "") strMyName = strprintf("x%u", GetRand(1000000000)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); diff --git a/src/net.cpp b/src/net.cpp index 234a5c5cdb..636db2952c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -214,6 +214,9 @@ bool AddLocal(const CService& addr, int nScore) if (!GetBoolArg("-discover", true) && nScore < LOCAL_MANUAL) return false; + if (IsLimited(addr)) + return false; + printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore); { @@ -242,14 +245,21 @@ bool AddLocal(const CNetAddr &addr, int nScore) /** Make a particular network entirely off-limits (no automatic connects to it) */ void SetLimited(enum Network net, bool fLimited) { + if (net == NET_UNROUTABLE) + return; LOCK(cs_mapLocalHost); vfLimited[net] = fLimited; } -bool IsLimited(const CNetAddr& addr) +bool IsLimited(enum Network net) { LOCK(cs_mapLocalHost); - return vfLimited[addr.GetNetwork()]; + return vfLimited[net]; +} + +bool IsLimited(const CNetAddr &addr) +{ + return IsLimited(addr.GetNetwork()); } /** vote for a local address */ @@ -57,6 +57,7 @@ enum }; void SetLimited(enum Network net, bool fLimited = true); +bool IsLimited(enum Network net); bool IsLimited(const CNetAddr& addr); bool AddLocal(const CService& addr, int nScore = LOCAL_NONE); bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); diff --git a/src/netbase.cpp b/src/netbase.cpp index 2131bdf75b..3fe42a7a74 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -711,7 +711,19 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { - if (IsIPv4()) + CService serv(*this, 0); +#ifdef USE_IPV6 + struct sockaddr_storage sockaddr; +#else + struct sockaddr sockaddr; +#endif + socklen_t socklen = sizeof(sockaddr); + if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) { + char name[1025] = ""; + if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) + return std::string(name); + } + if (IsIPv4()) return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); else return strprintf("%x:%x:%x:%x:%x:%x:%x:%x", diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index dfc85c66d6..d314e62b5a 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -324,6 +324,7 @@ void AddressBookPage::on_showQRCode_clicked() QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString(); QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this); + dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); } #endif diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index cf115c48f1..ab0a37abff 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -129,6 +129,53 @@ static void handleRunawayException(std::exception *e) exit(1); } +/** Help message for Bitcoin-Qt, shown with --help. */ +class HelpMessageBox: public QMessageBox +{ +public: + HelpMessageBox(QWidget *parent = 0); + + void exec(); +private: + QString header; + QString coreOptions; + QString uiOptions; +}; +#include <QSpacerItem> +#include <QGridLayout> +HelpMessageBox::HelpMessageBox(QWidget *parent): + QMessageBox(parent) +{ + header = tr("Bitcoin-Qt") + " " + tr("version") + " " + + QString::fromStdString(FormatFullVersion()) + "\n\n" + + tr("Usage:") + "\n" + + " bitcoin-qt [options] " + "\n"; + coreOptions = QString::fromStdString(HelpMessage()); + uiOptions = tr("UI options") + ":\n" + + " -lang=<lang> " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + + " -min " + tr("Start minimized") + "\n" + + " -splash " + tr("Show splash screen on startup (default: 1)") + "\n"; + + setWindowTitle(tr("Bitcoin-Qt")); + setTextFormat(Qt::PlainText); + // setMinimumWidth is ignored for QMessageBox so put in nonbreaking spaces to make it wider. + QChar em_space(0x2003); + setText(header + QString(em_space).repeated(40)); + setDetailedText(coreOptions + "\n" + uiOptions); +} + +void HelpMessageBox::exec() +{ +#if defined(WIN32) + // On windows, show a message box, as there is no stderr in windowed applications + QMessageBox::exec(); +#else + // On other operating systems, the expected action is to print the message to the console. + QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions; + fprintf(stderr, "%s", strUsage.toStdString().c_str()); +#endif +} + #ifdef WIN32 #define strncasecmp strnicmp #endif @@ -218,6 +265,15 @@ int main(int argc, char *argv[]) if (translator.load(lang_territory, ":/translations/")) app.installTranslator(&translator); + // 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")) + { + HelpMessageBox help; + help.exec(); + return 1; + } + QSplashScreen splash(QPixmap(":/images/splash"), 0); if (GetBoolArg("-splash", true) && !GetBoolArg("-min")) { @@ -238,7 +294,7 @@ int main(int argc, char *argv[]) BitcoinGUI window; guiref = &window; - if(AppInit2(argc, argv)) + if(AppInit2()) { { // Put this in a block, so that the Model objects are cleaned up before diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index ae9bf2a4b9..6b97d97656 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -9,6 +9,7 @@ #include "addressbookpage.h" #include "sendcoinsdialog.h" #include "messagepage.h" +#include "verifymessagedialog.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" @@ -257,6 +258,8 @@ void BitcoinGUI::createActions() changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); openRPCConsoleAction = new QAction(tr("&Debug window"), this); openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); + verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); + verifyMessageAction->setToolTip(tr("Verify a message signature")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); @@ -266,6 +269,7 @@ void BitcoinGUI::createActions() connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(verifyMessage())); } void BitcoinGUI::createMenuBar() @@ -285,6 +289,7 @@ void BitcoinGUI::createMenuBar() #ifndef FIRST_CLASS_MESSAGING file->addAction(messageAction); #endif + file->addAction(verifyMessageAction); file->addSeparator(); file->addAction(quitAction); @@ -408,6 +413,7 @@ void BitcoinGUI::createTrayIcon() trayIconMenu->addAction(openRPCConsoleAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(messageAction); + trayIconMenu->addAction(verifyMessageAction); #ifndef FIRST_CLASS_MESSAGING trayIconMenu->addSeparator(); #endif @@ -839,6 +845,13 @@ void BitcoinGUI::changePassphrase() dlg.exec(); } +void BitcoinGUI::verifyMessage() +{ + VerifyMessageDialog *dlg = new VerifyMessageDialog(walletModel->getAddressTableModel(), this); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); +} + void BitcoinGUI::unlockWallet() { if(!walletModel) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index bc3c9a1dfc..88e6d064d7 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -79,6 +79,7 @@ private: QAction *sendCoinsAction; QAction *addressBookAction; QAction *messageAction; + QAction *verifyMessageAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -163,6 +164,8 @@ private slots: void backupWallet(); /** Change encrypted wallet passphrase */ void changePassphrase(); + /** Verify a message signature */ + void verifyMessage(); /** Ask for pass phrase to unlock wallet temporarily */ void unlockWallet(); diff --git a/src/qt/forms/verifymessagedialog.ui b/src/qt/forms/verifymessagedialog.ui new file mode 100644 index 0000000000..6b7f94258b --- /dev/null +++ b/src/qt/forms/verifymessagedialog.ui @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VerifyMessageDialog</class> + <widget class="QDialog" name="VerifyMessageDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>494</width> + <height>342</height> + </rect> + </property> + <property name="windowTitle"> + <string>Verify Signed Message</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Enter the message and signature below (be careful to correctly copy newlines, spaces, tabs, and other invisible characters), and press apply to obtain the bitcoin address used to sign the message.</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="edMessage"/> + </item> + <item> + <widget class="QLineEdit" name="lnSig"> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Signature</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lnAddress"> + <property name="text"> + <string/> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="placeholderText"> + <string>Address</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblStatus"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="copyToClipboard"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Copy the currently selected address to the system clipboard</string> + </property> + <property name="text"> + <string>&Copy Address</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset> + </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> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set> + </property> + <property name="centerButtons"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources> + <include location="../bitcoin.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>VerifyMessageDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>VerifyMessageDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 23e6576772..22c0bfeebe 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -257,7 +257,7 @@ bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt) { QWidget *widget = static_cast<QWidget*>(obj); QString tooltip = widget->toolTip(); - if(!Qt::mightBeRichText(tooltip) && tooltip.size() > size_threshold) + if(tooltip.size() > size_threshold && !tooltip.startsWith("<qt/>") && !Qt::mightBeRichText(tooltip)) { // Prefix <qt/> to make sure Qt detects this as rich text // Escape the current message as HTML and replace \n by <br> diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp index d8e2007a2f..32e5462cee 100644 --- a/src/qt/qrcodedialog.cpp +++ b/src/qt/qrcodedialog.cpp @@ -15,7 +15,6 @@ QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enabl { ui->setupUi(this); setWindowTitle(QString("%1").arg(address)); - setAttribute(Qt::WA_DeleteOnClose); ui->chkReqPayment->setVisible(enableReq); ui->lnReqAmount->setVisible(enableReq); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 33b09952b7..51051f72f0 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -11,6 +11,7 @@ #include <QTextEdit> #include <QKeyEvent> #include <QUrl> +#include <QScrollBar> #include <boost/tokenizer.hpp> @@ -262,6 +263,8 @@ void RPCConsole::on_lineEdit_returnPressed() history.removeFirst(); // Set pointer to end of history historyPtr = history.size(); + // Scroll console view to end + scrollToEnd(); } } @@ -315,3 +318,9 @@ void RPCConsole::on_openDebugLogfileButton_clicked() { GUIUtil::openDebugLogfile(); } + +void RPCConsole::scrollToEnd() +{ + QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); +} diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 9c4fab497e..0a7b10f4a2 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -44,7 +44,8 @@ public slots: void setNumBlocks(int count); /** Go forward or back in history */ void browseHistory(int offset); - + /** Scroll console view to end */ + void scrollToEnd(); signals: // For RPC command executor void stopExecutor(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index b4029aa0d2..f6a3047a2b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -130,28 +130,28 @@ void SendCoinsDialog::on_sendButton_clicked() break; case WalletModel::AmountExceedsBalance: QMessageBox::warning(this, tr("Send Coins"), - tr("Amount exceeds your balance"), + tr("The amount exceeds your balance."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::AmountWithFeeExceedsBalance: QMessageBox::warning(this, tr("Send Coins"), - tr("Total exceeds your balance when the %1 transaction fee is included"). + tr("The total exceeds your balance when the %1 transaction fee is included."). arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::DuplicateAddress: QMessageBox::warning(this, tr("Send Coins"), - tr("Duplicate address found, can only send to each address once in one send operation"), + tr("Duplicate address found, can only send to each address once per send operation."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::TransactionCreationFailed: QMessageBox::warning(this, tr("Send Coins"), - tr("Error: Transaction creation failed "), + tr("Error: Transaction creation failed."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::TransactionCommitFailed: QMessageBox::warning(this, tr("Send Coins"), - tr("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."), + tr("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."), QMessageBox::Ok, QMessageBox::Ok); break; case WalletModel::Aborted: // User aborted, nothing to do diff --git a/src/qt/verifymessagedialog.cpp b/src/qt/verifymessagedialog.cpp new file mode 100644 index 0000000000..8842908718 --- /dev/null +++ b/src/qt/verifymessagedialog.cpp @@ -0,0 +1,75 @@ +#include "verifymessagedialog.h" +#include "ui_verifymessagedialog.h" + +#include <string> +#include <vector> + +#include <QDialogButtonBox> +#include <QAbstractButton> +#include <QClipboard> +#include <QMessageBox> + +#include "main.h" +#include "wallet.h" +#include "walletmodel.h" +#include "addresstablemodel.h" +#include "guiutil.h" + +VerifyMessageDialog::VerifyMessageDialog(AddressTableModel *addressModel, QWidget *parent) : + QDialog(parent), + ui(new Ui::VerifyMessageDialog), + model(addressModel) +{ + ui->setupUi(this); + + GUIUtil::setupAddressWidget(ui->lnAddress, this); +} + +VerifyMessageDialog::~VerifyMessageDialog() +{ + delete ui; +} + +bool VerifyMessageDialog::checkAddress() +{ + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->edMessage->document()->toPlainText().toStdString(); + uint256 hash = Hash(ss.begin(), ss.end()); + + bool invalid = true; + std::vector<unsigned char> vchSig = DecodeBase64(ui->lnSig->text().toStdString().c_str(), &invalid); + + if(invalid) + { + QMessageBox::warning(this, tr("Invalid Signature"), tr("The signature could not be decoded. Please check the signature and try again.")); + return false; + } + + CKey key; + if(!key.SetCompactSignature(hash, vchSig)) + { + QMessageBox::warning(this, tr("Invalid Signature"), tr("The signature did not match the message digest. Please check the signature and try again.")); + return false; + } + + CBitcoinAddress address(key.GetPubKey()); + QString qStringAddress = QString::fromStdString(address.ToString()); + ui->lnAddress->setText(qStringAddress); + ui->copyToClipboard->setEnabled(true); + + QString label = model->labelForAddress(qStringAddress); + ui->lblStatus->setText(label.isEmpty() ? tr("Address not found in address book.") : tr("Address found in address book: %1").arg(label)); + return true; +} + +void VerifyMessageDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + if(ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) + checkAddress(); +} + +void VerifyMessageDialog::on_copyToClipboard_clicked() +{ + QApplication::clipboard()->setText(ui->lnAddress->text()); +} diff --git a/src/qt/verifymessagedialog.h b/src/qt/verifymessagedialog.h new file mode 100644 index 0000000000..6a641f7731 --- /dev/null +++ b/src/qt/verifymessagedialog.h @@ -0,0 +1,36 @@ +#ifndef VERIFYMESSAGEDIALOG_H +#define VERIFYMESSAGEDIALOG_H + +#include <QDialog> + +class AddressTableModel; + +QT_BEGIN_NAMESPACE +class QAbstractButton; +QT_END_NAMESPACE + +namespace Ui { + class VerifyMessageDialog; +} + +class VerifyMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit VerifyMessageDialog(AddressTableModel *addressModel, QWidget *parent = 0); + ~VerifyMessageDialog(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + + void on_copyToClipboard_clicked(); + +private: + bool checkAddress(); + + Ui::VerifyMessageDialog *ui; + AddressTableModel *model; +}; + +#endif // VERIFYMESSAGEDIALOG_H |