diff options
-rw-r--r-- | doc/release-notes.md | 9 | ||||
-rw-r--r-- | src/Makefile.test.include | 2 | ||||
-rw-r--r-- | src/bitcoind.cpp | 3 | ||||
-rw-r--r-- | src/init.cpp | 157 | ||||
-rw-r--r-- | src/init.h | 4 | ||||
-rw-r--r-- | src/qt/bitcoin.cpp | 10 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 6 | ||||
-rw-r--r-- | src/test/bignum.h | 180 | ||||
-rw-r--r-- | src/test/scriptnum10.h | 183 | ||||
-rw-r--r-- | src/test/scriptnum_tests.cpp | 41 | ||||
-rw-r--r-- | src/torcontrol.cpp | 9 |
11 files changed, 333 insertions, 271 deletions
diff --git a/doc/release-notes.md b/doc/release-notes.md index 7db27f9fac..009baaed51 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -151,8 +151,8 @@ mining with the getblocktemplate protocol to a pool: this will affect you at the pool operator's discretion, which must be no later than BIP65 achieving its 951/1001 status. -Automatically listen on Tor ----------------------------- +Automatically use Tor hidden services +------------------------------------- Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket API, to create and destroy 'ephemeral' hidden services programmatically. @@ -160,8 +160,9 @@ Bitcoin Core has been updated to make use of this. This means that if Tor is running (and proper authorization is available), Bitcoin Core automatically creates a hidden service to listen on, without -manual configuration. This will positively affect the number of available -.onion nodes. +manual configuration. Bitcoin Core will also use Tor automatically to connect +to other .onion nodes if the control socket can be successfully opened. This +will positively affect the number of available .onion nodes and their usage. This new feature is enabled by default if Bitcoin Core is listening, and a connection to Tor can be made. It can be configured with the `-listenonion`, diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 2328d0b4cc..fafc1a2944 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -35,7 +35,7 @@ GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.r BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ - test/bignum.h \ + test/scriptnum10.h \ test/addrman_tests.cpp \ test/alert_tests.cpp \ test/allocator_tests.cpp \ diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index addf0e6a26..4cee2d3cf0 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -151,6 +151,9 @@ bool AppInit(int argc, char* argv[]) #endif SoftSetBoolArg("-server", true); + // Set this early so that parameter interactions go to console + InitLogging(); + InitParameterInteraction(); fRet = AppInit2(threadGroup, scheduler); } catch (const std::exception& e) { diff --git a/src/init.cpp b/src/init.cpp index 3ae3e44406..3e46958afc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -682,6 +682,91 @@ bool AppInitServers(boost::thread_group& threadGroup) return true; } +// Parameter interaction based on rules +void InitParameterInteraction() +{ + // when specifying an explicit binding address, you want to listen on it + // even when -connect or -proxy is specified + if (mapArgs.count("-bind")) { + if (SoftSetBoolArg("-listen", true)) + LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); + } + if (mapArgs.count("-whitebind")) { + if (SoftSetBoolArg("-listen", true)) + LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); + } + + if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { + // when only connecting to trusted nodes, do not seed via DNS, or listen by default + if (SoftSetBoolArg("-dnsseed", false)) + LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); + if (SoftSetBoolArg("-listen", false)) + LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); + } + + if (mapArgs.count("-proxy")) { + // to protect privacy, do not listen by default if a default proxy server is specified + if (SoftSetBoolArg("-listen", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); + // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1 + // to listen locally, so don't rely on this happening through -listen below. + if (SoftSetBoolArg("-upnp", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__); + // to protect privacy, do not discover addresses by default + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); + } + + if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { + // do not map ports or try to retrieve public IP when not listening (pointless) + if (SoftSetBoolArg("-upnp", false)) + LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); + if (SoftSetBoolArg("-listenonion", false)) + LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__); + } + + if (mapArgs.count("-externalip")) { + // if an explicit public IP is specified, do not try to find others + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); + } + + if (GetBoolArg("-salvagewallet", false)) { + // Rewrite just private keys: rescan to find transactions + if (SoftSetBoolArg("-rescan", true)) + LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); + } + + // -zapwallettx implies a rescan + if (GetBoolArg("-zapwallettxes", false)) { + if (SoftSetBoolArg("-rescan", true)) + LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__); + } + + // disable walletbroadcast and whitelistalwaysrelay in blocksonly mode + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) { + if (SoftSetBoolArg("-whitelistalwaysrelay", false)) + LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistalwaysrelay=0\n", __func__); +#ifdef ENABLE_WALLET + if (SoftSetBoolArg("-walletbroadcast", false)) + LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); +#endif + } +} + +void InitLogging() +{ + fPrintToConsole = GetBoolArg("-printtoconsole", false); + fLogTimestamps = GetBoolArg("-logtimestamps", true); + fLogTimeMicros = GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); + fLogIPs = GetBoolArg("-logips", false); + + LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); +} + /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ @@ -746,74 +831,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 2: parameter interactions const CChainParams& chainparams = Params(); - // Set this early so that parameter interactions go to console - fPrintToConsole = GetBoolArg("-printtoconsole", false); - fLogTimestamps = GetBoolArg("-logtimestamps", true); - fLogTimeMicros = GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); - fLogIPs = GetBoolArg("-logips", false); - - LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); - - // when specifying an explicit binding address, you want to listen on it - // even when -connect or -proxy is specified - if (mapArgs.count("-bind")) { - if (SoftSetBoolArg("-listen", true)) - LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); - } - if (mapArgs.count("-whitebind")) { - if (SoftSetBoolArg("-listen", true)) - LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); - } - if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { - // when only connecting to trusted nodes, do not seed via DNS, or listen by default - if (SoftSetBoolArg("-dnsseed", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); - if (SoftSetBoolArg("-listen", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); - } - - if (mapArgs.count("-proxy")) { - // to protect privacy, do not listen by default if a default proxy server is specified - if (SoftSetBoolArg("-listen", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); - // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1 - // to listen locally, so don't rely on this happening through -listen below. - if (SoftSetBoolArg("-upnp", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__); - // to protect privacy, do not discover addresses by default - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); - } - - if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { - // do not map ports or try to retrieve public IP when not listening (pointless) - if (SoftSetBoolArg("-upnp", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); - if (SoftSetBoolArg("-listenonion", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__); - } - - if (mapArgs.count("-externalip")) { - // if an explicit public IP is specified, do not try to find others - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); - } - - if (GetBoolArg("-salvagewallet", false)) { - // Rewrite just private keys: rescan to find transactions - if (SoftSetBoolArg("-rescan", true)) - LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); - } - - // -zapwallettx implies a rescan - if (GetBoolArg("-zapwallettxes", false)) { - if (SoftSetBoolArg("-rescan", true)) - LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__); - } // if using block pruning, then disable txindex if (GetArg("-prune", 0)) { @@ -1031,7 +1049,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (fPrintToDebugLog) OpenDebugLog(); +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); +#else + LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION)); +#endif + #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); #endif diff --git a/src/init.h b/src/init.h index 8cd51b0286..d4872e7794 100644 --- a/src/init.h +++ b/src/init.h @@ -23,6 +23,10 @@ bool ShutdownRequested(); /** Interrupt threads */ void Interrupt(boost::thread_group& threadGroup); void Shutdown(); +//!Initialize the logging infrastructure +void InitLogging(); +//!Parameter interaction: change current parameters depending on various rules +void InitParameterInteraction(); bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler); /** The help message mode determines what help message to show */ diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 06a6c239ef..d407e539ef 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -201,6 +201,8 @@ public: /// Create payment server void createPaymentServer(); #endif + /// parameter interaction/setup based on rules + void parameterSetup(); /// Create options model void createOptionsModel(bool resetSettings); /// Create main window @@ -397,6 +399,12 @@ void BitcoinApplication::startThread() coreThread->start(); } +void BitcoinApplication::parameterSetup() +{ + InitLogging(); + InitParameterInteraction(); +} + void BitcoinApplication::requestInitialize() { qDebug() << __func__ << ": Requesting initialize"; @@ -644,6 +652,8 @@ int main(int argc, char *argv[]) // Install qDebug() message handler to route to debug.log qInstallMessageHandler(DebugMessageHandler); #endif + // Allow parameter interaction before we create the options model + app.parameterSetup(); // Load GUI settings from QSettings app.createOptionsModel(mapArgs.count("-resetguisettings") != 0); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 619c8631ae..b2b4fd0fab 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -263,7 +263,13 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) : connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); // set library version labels + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); +#else + ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION)); +#endif + #ifdef ENABLE_WALLET ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); #else diff --git a/src/test/bignum.h b/src/test/bignum.h deleted file mode 100644 index e7aeee9db6..0000000000 --- a/src/test/bignum.h +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_TEST_BIGNUM_H -#define BITCOIN_TEST_BIGNUM_H - -#include <algorithm> -#include <limits> -#include <stdexcept> -#include <stdint.h> -#include <string> -#include <vector> - -#include <openssl/bn.h> - -class bignum_error : public std::runtime_error -{ -public: - explicit bignum_error(const std::string& str) : std::runtime_error(str) {} -}; - - -/** C++ wrapper for BIGNUM (OpenSSL bignum) */ -class CBigNum : public BIGNUM -{ -public: - CBigNum() - { - BN_init(this); - } - - CBigNum(const CBigNum& b) - { - BN_init(this); - if (!BN_copy(this, &b)) - { - BN_clear_free(this); - throw bignum_error("CBigNum::CBigNum(const CBigNum&): BN_copy failed"); - } - } - - CBigNum& operator=(const CBigNum& b) - { - if (!BN_copy(this, &b)) - throw bignum_error("CBigNum::operator=: BN_copy failed"); - return (*this); - } - - ~CBigNum() - { - BN_clear_free(this); - } - - CBigNum(long long n) { BN_init(this); setint64(n); } - - explicit CBigNum(const std::vector<unsigned char>& vch) - { - BN_init(this); - setvch(vch); - } - - int getint() const - { - BN_ULONG n = BN_get_word(this); - if (!BN_is_negative(this)) - return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n); - else - return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n); - } - - void setint64(int64_t sn) - { - unsigned char pch[sizeof(sn) + 6]; - unsigned char* p = pch + 4; - bool fNegative; - uint64_t n; - - if (sn < (int64_t)0) - { - // Since the minimum signed integer cannot be represented as positive so long as its type is signed, - // and it's not well-defined what happens if you make it unsigned before negating it, - // we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate - n = -(sn + 1); - ++n; - fNegative = true; - } else { - n = sn; - fNegative = false; - } - - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = (fNegative ? 0x80 : 0); - else if (fNegative) - c |= 0x80; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - void setvch(const std::vector<unsigned char>& vch) - { - std::vector<unsigned char> vch2(vch.size() + 4); - unsigned int nSize = vch.size(); - // BIGNUM's byte stream format expects 4 bytes of - // big endian size data info at the front - vch2[0] = (nSize >> 24) & 0xff; - vch2[1] = (nSize >> 16) & 0xff; - vch2[2] = (nSize >> 8) & 0xff; - vch2[3] = (nSize >> 0) & 0xff; - // swap data to big endian - reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); - BN_mpi2bn(&vch2[0], vch2.size(), this); - } - - std::vector<unsigned char> getvch() const - { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize <= 4) - return std::vector<unsigned char>(); - std::vector<unsigned char> vch(nSize); - BN_bn2mpi(this, &vch[0]); - vch.erase(vch.begin(), vch.begin() + 4); - reverse(vch.begin(), vch.end()); - return vch; - } - - friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); -}; - - - -inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_add(&r, &a, &b)) - throw bignum_error("CBigNum::operator+: BN_add failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_sub(&r, &a, &b)) - throw bignum_error("CBigNum::operator-: BN_sub failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a) -{ - CBigNum r(a); - BN_set_negative(&r, !BN_is_negative(&r)); - return r; -} - -inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } -inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } -inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } -inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } -inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } -inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } - -#endif // BITCOIN_TEST_BIGNUM_H diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h new file mode 100644 index 0000000000..00419746b7 --- /dev/null +++ b/src/test/scriptnum10.h @@ -0,0 +1,183 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_SCRIPTNUM10_H +#define BITCOIN_TEST_SCRIPTNUM10_H + +#include <algorithm> +#include <limits> +#include <stdexcept> +#include <stdint.h> +#include <string> +#include <vector> +#include "assert.h" + +class scriptnum10_error : public std::runtime_error +{ +public: + explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {} +}; + +class CScriptNum10 +{ +/** + * The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison. + */ +public: + + explicit CScriptNum10(const int64_t& n) + { + m_value = n; + } + + static const size_t nDefaultMaxNumSize = 4; + + explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal, + const size_t nMaxNumSize = nDefaultMaxNumSize) + { + if (vch.size() > nMaxNumSize) { + throw scriptnum10_error("script number overflow"); + } + if (fRequireMinimal && vch.size() > 0) { + // Check that the number is encoded with the minimum possible + // number of bytes. + // + // If the most-significant-byte - excluding the sign bit - is zero + // then we're not minimal. Note how this test also rejects the + // negative-zero encoding, 0x80. + if ((vch.back() & 0x7f) == 0) { + // One exception: if there's more than one byte and the most + // significant bit of the second-most-significant-byte is set + // it would conflict with the sign bit. An example of this case + // is +-255, which encode to 0xff00 and 0xff80 respectively. + // (big-endian). + if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) { + throw scriptnum10_error("non-minimally encoded script number"); + } + } + } + m_value = set_vch(vch); + } + + inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } + inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } + inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } + inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } + inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } + inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } + + inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); } + inline bool operator!=(const CScriptNum10& rhs) const { return operator!=(rhs.m_value); } + inline bool operator<=(const CScriptNum10& rhs) const { return operator<=(rhs.m_value); } + inline bool operator< (const CScriptNum10& rhs) const { return operator< (rhs.m_value); } + inline bool operator>=(const CScriptNum10& rhs) const { return operator>=(rhs.m_value); } + inline bool operator> (const CScriptNum10& rhs) const { return operator> (rhs.m_value); } + + inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);} + inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);} + inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); } + inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); } + + inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); } + inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); } + + inline CScriptNum10 operator-() const + { + assert(m_value != std::numeric_limits<int64_t>::min()); + return CScriptNum10(-m_value); + } + + inline CScriptNum10& operator=( const int64_t& rhs) + { + m_value = rhs; + return *this; + } + + inline CScriptNum10& operator+=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || + (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)); + m_value += rhs; + return *this; + } + + inline CScriptNum10& operator-=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || + (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)); + m_value -= rhs; + return *this; + } + + int getint() const + { + if (m_value > std::numeric_limits<int>::max()) + return std::numeric_limits<int>::max(); + else if (m_value < std::numeric_limits<int>::min()) + return std::numeric_limits<int>::min(); + return m_value; + } + + std::vector<unsigned char> getvch() const + { + return serialize(m_value); + } + + static std::vector<unsigned char> serialize(const int64_t& value) + { + if(value == 0) + return std::vector<unsigned char>(); + + std::vector<unsigned char> result; + const bool neg = value < 0; + uint64_t absvalue = neg ? -value : value; + + while(absvalue) + { + result.push_back(absvalue & 0xff); + absvalue >>= 8; + } + +// - If the most significant byte is >= 0x80 and the value is positive, push a +// new zero-byte to make the significant byte < 0x80 again. + +// - If the most significant byte is >= 0x80 and the value is negative, push a +// new 0x80 byte that will be popped off when converting to an integral. + +// - If the most significant byte is < 0x80 and the value is negative, add +// 0x80 to it, since it will be subtracted and interpreted as a negative when +// converting to an integral. + + if (result.back() & 0x80) + result.push_back(neg ? 0x80 : 0); + else if (neg) + result.back() |= 0x80; + + return result; + } + +private: + static int64_t set_vch(const std::vector<unsigned char>& vch) + { + if (vch.empty()) + return 0; + + int64_t result = 0; + for (size_t i = 0; i != vch.size(); ++i) + result |= static_cast<int64_t>(vch[i]) << 8*i; + + // 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 -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); + + return result; + } + + int64_t m_value; +}; + + +#endif // BITCOIN_TEST_BIGNUM_H diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index d95724dbe1..2405ab3ffc 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "bignum.h" +#include "scriptnum10.h" #include "script/script.h" #include "test/test_bitcoin.h" @@ -16,45 +16,48 @@ static const int64_t values[] = \ { 0, 1, CHAR_MIN, CHAR_MAX, UCHAR_MAX, SHRT_MIN, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX, LONG_MIN, LONG_MAX }; static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000}; -static bool verify(const CBigNum& bignum, const CScriptNum& scriptnum) +static bool verify(const CScriptNum10& bignum, const CScriptNum& scriptnum) { return bignum.getvch() == scriptnum.getvch() && bignum.getint() == scriptnum.getint(); } static void CheckCreateVch(const int64_t& num) { - CBigNum bignum(num); + CScriptNum10 bignum(num); CScriptNum scriptnum(num); BOOST_CHECK(verify(bignum, scriptnum)); - CBigNum bignum2(bignum.getvch()); + std::vector<unsigned char> vch = bignum.getvch(); + + CScriptNum10 bignum2(bignum.getvch(), false); + vch = scriptnum.getvch(); CScriptNum scriptnum2(scriptnum.getvch(), false); BOOST_CHECK(verify(bignum2, scriptnum2)); - CBigNum bignum3(scriptnum2.getvch()); + CScriptNum10 bignum3(scriptnum2.getvch(), false); CScriptNum scriptnum3(bignum2.getvch(), false); BOOST_CHECK(verify(bignum3, scriptnum3)); } static void CheckCreateInt(const int64_t& num) { - CBigNum bignum(num); + CScriptNum10 bignum(num); CScriptNum scriptnum(num); BOOST_CHECK(verify(bignum, scriptnum)); - BOOST_CHECK(verify(bignum.getint(), CScriptNum(scriptnum.getint()))); - BOOST_CHECK(verify(scriptnum.getint(), CScriptNum(bignum.getint()))); - BOOST_CHECK(verify(CBigNum(scriptnum.getint()).getint(), CScriptNum(CScriptNum(bignum.getint()).getint()))); + BOOST_CHECK(verify(CScriptNum10(bignum.getint()), CScriptNum(scriptnum.getint()))); + BOOST_CHECK(verify(CScriptNum10(scriptnum.getint()), CScriptNum(bignum.getint()))); + BOOST_CHECK(verify(CScriptNum10(CScriptNum10(scriptnum.getint()).getint()), CScriptNum(CScriptNum(bignum.getint()).getint()))); } static void CheckAdd(const int64_t& num1, const int64_t& num2) { - const CBigNum bignum1(num1); - const CBigNum bignum2(num2); + const CScriptNum10 bignum1(num1); + const CScriptNum10 bignum2(num2); const CScriptNum scriptnum1(num1); const CScriptNum scriptnum2(num2); - CBigNum bignum3(num1); - CBigNum bignum4(num1); + CScriptNum10 bignum3(num1); + CScriptNum10 bignum4(num1); CScriptNum scriptnum3(num1); CScriptNum scriptnum4(num1); @@ -71,7 +74,7 @@ static void CheckAdd(const int64_t& num1, const int64_t& num2) static void CheckNegate(const int64_t& num) { - const CBigNum bignum(num); + const CScriptNum10 bignum(num); const CScriptNum scriptnum(num); // -INT64_MIN is undefined @@ -81,8 +84,8 @@ static void CheckNegate(const int64_t& num) static void CheckSubtract(const int64_t& num1, const int64_t& num2) { - const CBigNum bignum1(num1); - const CBigNum bignum2(num2); + const CScriptNum10 bignum1(num1); + const CScriptNum10 bignum2(num2); const CScriptNum scriptnum1(num1); const CScriptNum scriptnum2(num2); bool invalid = false; @@ -107,8 +110,8 @@ static void CheckSubtract(const int64_t& num1, const int64_t& num2) static void CheckCompare(const int64_t& num1, const int64_t& num2) { - const CBigNum bignum1(num1); - const CBigNum bignum2(num2); + const CScriptNum10 bignum1(num1); + const CScriptNum10 bignum2(num2); const CScriptNum scriptnum1(num1); const CScriptNum scriptnum2(num2); @@ -149,7 +152,7 @@ static void RunCreate(const int64_t& num) CheckCreateVch(num); else { - BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum_error); + BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum10_error); } } diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 08644f2968..31a2917203 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -449,6 +449,15 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r { if (reply.code == 250) { LogPrint("tor", "tor: Authentication succesful\n"); + + // Now that we know Tor is running setup the proxy for onion addresses + // if -onion isn't set to something else. + if (GetArg("-onion", "") == "") { + proxyType addrOnion = proxyType(CService("127.0.0.1", 9050), true); + SetProxy(NET_TOR, addrOnion); + SetReachable(NET_TOR); + } + // Finally - now create the service if (private_key.empty()) // No private key, generate one private_key = "NEW:BEST"; |