aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am6
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/alert.cpp1
-rw-r--r--src/bitcoin-cli.cpp2
-rw-r--r--src/bitcoin-tx.cpp1
-rw-r--r--src/bitcoind.cpp1
-rw-r--r--src/compat.h25
-rw-r--r--src/core.h3
-rw-r--r--src/core_write.cpp1
-rw-r--r--src/crypter.cpp1
-rw-r--r--src/db.cpp2
-rw-r--r--src/init.cpp2
-rw-r--r--src/keystore.cpp1
-rw-r--r--src/main.cpp62
-rw-r--r--src/main.h64
-rw-r--r--src/miner.cpp6
-rw-r--r--src/net.cpp155
-rw-r--r--src/net.h161
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/noui.cpp1
-rw-r--r--src/pow.cpp1
-rw-r--r--src/qt/bitcoin.cpp1
-rw-r--r--src/qt/bitcoingui.cpp1
-rw-r--r--src/qt/clientmodel.cpp1
-rw-r--r--src/qt/optionsdialog.cpp1
-rw-r--r--src/qt/paymentserver.cpp1
-rw-r--r--src/qt/transactiondesc.cpp1
-rw-r--r--src/qt/utilitydialog.cpp5
-rw-r--r--src/random.cpp4
-rw-r--r--src/rpcblockchain.cpp1
-rw-r--r--src/rpcdump.cpp2
-rw-r--r--src/rpcmining.cpp1
-rw-r--r--src/rpcprotocol.cpp4
-rw-r--r--src/rpcserver.cpp6
-rw-r--r--src/script.cpp3
-rw-r--r--src/script.h3
-rw-r--r--src/test/DoS_tests.cpp1
-rw-r--r--src/test/alert_tests.cpp1
-rw-r--r--src/test/allocator_tests.cpp2
-rw-r--r--src/test/base32_tests.cpp2
-rw-r--r--src/test/base64_tests.cpp2
-rw-r--r--src/test/checkblock_tests.cpp1
-rw-r--r--src/test/crypto_tests.cpp2
-rw-r--r--src/test/hash_tests.cpp2
-rw-r--r--src/test/test_bitcoin.cpp1
-rw-r--r--src/test/timedata_tests.cpp38
-rw-r--r--src/test/util_tests.cpp28
-rw-r--r--src/timedata.cpp6
-rw-r--r--src/timedata.h59
-rw-r--r--src/tinyformat.h1
-rw-r--r--src/txdb.cpp1
-rw-r--r--src/txmempool.cpp1
-rw-r--r--src/uint256.cpp3
-rw-r--r--src/util.cpp583
-rw-r--r--src/util.h300
-rw-r--r--src/utilmoneystr.cpp75
-rw-r--r--src/utilmoneystr.h19
-rw-r--r--src/utilstrencodings.cpp496
-rw-r--r--src/utilstrencodings.h97
-rw-r--r--src/utiltime.cpp66
-rw-r--r--src/utiltime.h20
-rw-r--r--src/version.cpp28
-rw-r--r--src/version.h4
-rw-r--r--src/wallet.cpp25
-rw-r--r--src/wallet.h24
-rw-r--r--src/walletdb.cpp3
66 files changed, 1294 insertions, 1131 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6c67dee7d5..655bfc88c3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -109,6 +109,9 @@ BITCOIN_CORE_H = \
ui_interface.h \
uint256.h \
util.h \
+ utilstrencodings.h \
+ utilmoneystr.h \
+ utiltime.h \
version.h \
walletdb.h \
wallet.h \
@@ -219,6 +222,9 @@ libbitcoin_util_a_SOURCES = \
sync.cpp \
uint256.cpp \
util.cpp \
+ utilstrencodings.cpp \
+ utilmoneystr.cpp \
+ utiltime.cpp \
version.cpp \
$(BITCOIN_CORE_H)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index cc407f679f..b4360831bb 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -61,6 +61,7 @@ BITCOIN_TESTS =\
test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \
test/test_bitcoin.cpp \
+ test/timedata_tests.cpp \
test/transaction_tests.cpp \
test/uint256_tests.cpp \
test/univalue_tests.cpp \
diff --git a/src/alert.cpp b/src/alert.cpp
index 2cd684cc4c..3271ecfbfd 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -19,6 +19,7 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
using namespace std;
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 0609adcab3..871aaf93df 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -8,6 +8,8 @@
#include "rpcclient.h"
#include "rpcprotocol.h"
#include "chainparamsbase.h"
+#include "utilstrencodings.h"
+#include "version.h"
#include <boost/filesystem/operations.hpp>
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 6cd2768d70..75f0fb69f2 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -4,6 +4,7 @@
#include "base58.h"
#include "util.h"
+#include "utilmoneystr.h"
#include "core.h"
#include "main.h" // for MAX_BLOCK_SIZE
#include "keystore.h"
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 880955481b..5be8708979 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -12,6 +12,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
/* Introduction text for doxygen: */
diff --git a/src/compat.h b/src/compat.h
index 52c7817130..4fc28a36e0 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -59,4 +59,29 @@ typedef u_int SOCKET;
#define SOCKET_ERROR -1
#endif
+#ifdef WIN32
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#endif
+#else
+#define MAX_PATH 1024
+#endif
+
+// As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0
+#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
+
+#ifndef WIN32
+// PRIO_MAX is not defined on Solaris
+#ifndef PRIO_MAX
+#define PRIO_MAX 20
+#endif
+#define THREAD_PRIORITY_LOWEST PRIO_MAX
+#define THREAD_PRIORITY_BELOW_NORMAL 2
+#define THREAD_PRIORITY_NORMAL 0
+#define THREAD_PRIORITY_ABOVE_NORMAL (-2)
+#endif
+
#endif // _BITCOIN_COMPAT_H
diff --git a/src/core.h b/src/core.h
index 9552f70254..e3ceac97aa 100644
--- a/src/core.h
+++ b/src/core.h
@@ -14,6 +14,9 @@
class CTransaction;
+static const int64_t COIN = 100000000;
+static const int64_t CENT = 1000000;
+
/** No amount larger than this (in satoshi) is valid */
static const int64_t MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
diff --git a/src/core_write.cpp b/src/core_write.cpp
index 37dd69f7b8..b395b5c090 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -8,6 +8,7 @@
#include "core.h"
#include "serialize.h"
#include "util.h"
+#include "utilmoneystr.h"
#include "base58.h"
using namespace std;
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 122e06d97e..8aa2bb0517 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -5,6 +5,7 @@
#include "crypter.h"
#include "script.h"
+#include "util.h"
#include <string>
#include <vector>
diff --git a/src/db.cpp b/src/db.cpp
index eb40f3cc40..8c139843a1 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -9,6 +9,7 @@
#include "hash.h"
#include "protocol.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <stdint.h>
@@ -17,6 +18,7 @@
#endif
#include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
#include <boost/version.hpp>
#include <openssl/rand.h>
diff --git a/src/init.cpp b/src/init.cpp
index 708e6386aa..e972413c4b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -19,6 +19,7 @@
#include "txdb.h"
#include "ui_interface.h"
#include "util.h"
+#include "utilmoneystr.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
@@ -36,6 +37,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
+#include <boost/thread.hpp>
#include <openssl/crypto.h>
using namespace boost;
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 2a4c88d565..c6322eadce 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -8,6 +8,7 @@
#include "crypter.h"
#include "key.h"
#include "script.h"
+#include "util.h"
#include <boost/foreach.hpp>
diff --git a/src/main.cpp b/src/main.cpp
index 1c9b3f861b..6567c77e93 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -24,6 +24,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
+#include <boost/thread.hpp>
using namespace std;
using namespace boost;
@@ -4655,7 +4656,68 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
}
+bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock)
+{
+ // Open history file to append
+ CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
+ if (!fileout)
+ return error("CBlockUndo::WriteToDisk : OpenUndoFile failed");
+
+ // Write index header
+ unsigned int nSize = fileout.GetSerializeSize(*this);
+ fileout << FLATDATA(Params().MessageStart()) << nSize;
+
+ // Write undo data
+ long fileOutPos = ftell(fileout);
+ if (fileOutPos < 0)
+ return error("CBlockUndo::WriteToDisk : ftell failed");
+ pos.nPos = (unsigned int)fileOutPos;
+ fileout << *this;
+
+ // calculate & write checksum
+ CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
+ hasher << hashBlock;
+ hasher << *this;
+ fileout << hasher.GetHash();
+
+ // Flush stdio buffers and commit to disk before returning
+ fflush(fileout);
+ if (!IsInitialBlockDownload())
+ FileCommit(fileout);
+
+ return true;
+}
+
+bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock)
+{
+ // Open history file to read
+ CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
+ if (!filein)
+ return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed");
+
+ // Read block
+ uint256 hashChecksum;
+ try {
+ filein >> *this;
+ filein >> hashChecksum;
+ }
+ catch (std::exception &e) {
+ return error("%s : Deserialize or I/O error - %s", __func__, e.what());
+ }
+
+ // Verify checksum
+ CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
+ hasher << hashBlock;
+ hasher << *this;
+ if (hashChecksum != hasher.GetHash())
+ return error("CBlockUndo::ReadFromDisk : Checksum mismatch");
+
+ return true;
+}
+ std::string CBlockFileInfo::ToString() const {
+ return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str());
+ }
diff --git a/src/main.h b/src/main.h
index f93b78d8e5..e5357cbfdd 100644
--- a/src/main.h
+++ b/src/main.h
@@ -312,64 +312,8 @@ public:
READWRITE(vtxundo);
)
- bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock)
- {
- // Open history file to append
- CAutoFile fileout = CAutoFile(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
- if (!fileout)
- return error("CBlockUndo::WriteToDisk : OpenUndoFile failed");
-
- // Write index header
- unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(Params().MessageStart()) << nSize;
-
- // Write undo data
- long fileOutPos = ftell(fileout);
- if (fileOutPos < 0)
- return error("CBlockUndo::WriteToDisk : ftell failed");
- pos.nPos = (unsigned int)fileOutPos;
- fileout << *this;
-
- // calculate & write checksum
- CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
- hasher << hashBlock;
- hasher << *this;
- fileout << hasher.GetHash();
-
- // Flush stdio buffers and commit to disk before returning
- fflush(fileout);
- if (!IsInitialBlockDownload())
- FileCommit(fileout);
-
- return true;
- }
-
- bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock)
- {
- // Open history file to read
- CAutoFile filein = CAutoFile(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION);
- if (!filein)
- return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed");
-
- // Read block
- uint256 hashChecksum;
- try {
- filein >> *this;
- filein >> hashChecksum;
- }
- catch (std::exception &e) {
- return error("%s : Deserialize or I/O error - %s", __func__, e.what());
- }
-
- // Verify checksum
- CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
- hasher << hashBlock;
- hasher << *this;
- if (hashChecksum != hasher.GetHash())
- return error("CBlockUndo::ReadFromDisk : Checksum mismatch");
-
- return true;
- }
+ bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock);
+ bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock);
};
@@ -625,9 +569,7 @@ public:
SetNull();
}
- std::string ToString() const {
- return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str());
- }
+ std::string ToString() const;
// update statistics (does not update nSize)
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
diff --git a/src/miner.cpp b/src/miner.cpp
index 06acff1c33..8696edcf6e 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -3,8 +3,6 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <inttypes.h>
-
#include "miner.h"
#include "core.h"
@@ -12,10 +10,14 @@
#include "main.h"
#include "net.h"
#include "pow.h"
+#include "util.h"
+#include "utilmoneystr.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
+#include <boost/thread.hpp>
+
using namespace std;
//////////////////////////////////////////////////////////////////////////////
diff --git a/src/net.cpp b/src/net.cpp
index cae9b70da7..e2adba8517 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -28,6 +28,7 @@
#endif
#include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900
@@ -2037,3 +2038,157 @@ bool CAddrDB::Read(CAddrMan& addr)
return true;
}
+
+unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
+unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
+
+CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000)
+{
+ nServices = 0;
+ hSocket = hSocketIn;
+ nRecvVersion = INIT_PROTO_VERSION;
+ nLastSend = 0;
+ nLastRecv = 0;
+ nSendBytes = 0;
+ nRecvBytes = 0;
+ nTimeConnected = GetTime();
+ addr = addrIn;
+ addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
+ nVersion = 0;
+ strSubVer = "";
+ fWhitelisted = false;
+ fOneShot = false;
+ fClient = false; // set by version message
+ fInbound = fInboundIn;
+ fNetworkNode = false;
+ fSuccessfullyConnected = false;
+ fDisconnect = false;
+ nRefCount = 0;
+ nSendSize = 0;
+ nSendOffset = 0;
+ hashContinue = 0;
+ pindexLastGetBlocksBegin = 0;
+ hashLastGetBlocksEnd = 0;
+ nStartingHeight = -1;
+ fStartSync = false;
+ fGetAddr = false;
+ fRelayTxes = false;
+ setInventoryKnown.max_size(SendBufferSize() / 1000);
+ pfilter = new CBloomFilter();
+ nPingNonceSent = 0;
+ nPingUsecStart = 0;
+ nPingUsecTime = 0;
+ fPingQueued = false;
+
+ {
+ LOCK(cs_nLastNodeId);
+ id = nLastNodeId++;
+ }
+
+ if (fLogIPs)
+ LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
+ else
+ LogPrint("net", "Added connection peer=%d\n", id);
+
+ // Be shy and don't send version until we hear
+ if (hSocket != INVALID_SOCKET && !fInbound)
+ PushVersion();
+
+ GetNodeSignals().InitializeNode(GetId(), this);
+}
+
+CNode::~CNode()
+{
+ CloseSocket(hSocket);
+
+ if (pfilter)
+ delete pfilter;
+
+ GetNodeSignals().FinalizeNode(GetId());
+}
+
+void CNode::AskFor(const CInv& inv)
+{
+ // We're using mapAskFor as a priority queue,
+ // the key is the earliest time the request can be sent
+ int64_t nRequestTime;
+ limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
+ if (it != mapAlreadyAskedFor.end())
+ nRequestTime = it->second;
+ else
+ nRequestTime = 0;
+ LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id);
+
+ // Make sure not to reuse time indexes to keep things in the same order
+ int64_t nNow = GetTimeMicros() - 1000000;
+ static int64_t nLastTime;
+ ++nLastTime;
+ nNow = std::max(nNow, nLastTime);
+ nLastTime = nNow;
+
+ // Each retry is 2 minutes after the last
+ nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
+ if (it != mapAlreadyAskedFor.end())
+ mapAlreadyAskedFor.update(it, nRequestTime);
+ else
+ mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
+ mapAskFor.insert(std::make_pair(nRequestTime, inv));
+}
+
+void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend)
+{
+ ENTER_CRITICAL_SECTION(cs_vSend);
+ assert(ssSend.size() == 0);
+ ssSend << CMessageHeader(pszCommand, 0);
+ LogPrint("net", "sending: %s ", pszCommand);
+}
+
+void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
+{
+ ssSend.clear();
+
+ LEAVE_CRITICAL_SECTION(cs_vSend);
+
+ LogPrint("net", "(aborted)\n");
+}
+
+void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
+{
+ // The -*messagestest options are intentionally not documented in the help message,
+ // since they are only used during development to debug the networking code and are
+ // not intended for end-users.
+ if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
+ {
+ LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
+ AbortMessage();
+ return;
+ }
+ if (mapArgs.count("-fuzzmessagestest"))
+ Fuzz(GetArg("-fuzzmessagestest", 10));
+
+ if (ssSend.size() == 0)
+ return;
+
+ // Set the size
+ unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
+ memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize));
+
+ // Set the checksum
+ uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
+ unsigned int nChecksum = 0;
+ memcpy(&nChecksum, &hash, sizeof(nChecksum));
+ assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
+ memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
+
+ LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
+
+ std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
+ ssSend.GetAndClear(*it);
+ nSendSize += (*it).size();
+
+ // If write queue empty, attempt "optimistic write"
+ if (it == vSendMsg.begin())
+ SocketSendData(this);
+
+ LEAVE_CRITICAL_SECTION(cs_vSend);
+}
diff --git a/src/net.h b/src/net.h
index 1a7b3c00b8..bfad32b2c1 100644
--- a/src/net.h
+++ b/src/net.h
@@ -16,7 +16,7 @@
#include "random.h"
#include "sync.h"
#include "uint256.h"
-#include "util.h"
+#include "utilstrencodings.h"
#include <deque>
#include <stdint.h>
@@ -25,6 +25,7 @@
#include <arpa/inet.h>
#endif
+#include <boost/filesystem/path.hpp>
#include <boost/foreach.hpp>
#include <boost/signals2/signal.hpp>
@@ -51,8 +52,8 @@ static const bool DEFAULT_UPNP = USE_UPNP;
static const bool DEFAULT_UPNP = false;
#endif
-inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
-inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
+unsigned int ReceiveFloodSize();
+unsigned int SendBufferSize();
void AddOneShot(std::string strDest);
bool RecvLine(SOCKET hSocket, std::string& strLine);
@@ -300,70 +301,8 @@ public:
// 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)
- {
- nServices = 0;
- hSocket = hSocketIn;
- nRecvVersion = INIT_PROTO_VERSION;
- nLastSend = 0;
- nLastRecv = 0;
- nSendBytes = 0;
- nRecvBytes = 0;
- nTimeConnected = GetTime();
- addr = addrIn;
- addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
- nVersion = 0;
- strSubVer = "";
- fWhitelisted = false;
- fOneShot = false;
- fClient = false; // set by version message
- fInbound = fInboundIn;
- fNetworkNode = false;
- fSuccessfullyConnected = false;
- fDisconnect = false;
- nRefCount = 0;
- nSendSize = 0;
- nSendOffset = 0;
- hashContinue = 0;
- pindexLastGetBlocksBegin = 0;
- hashLastGetBlocksEnd = 0;
- nStartingHeight = -1;
- fStartSync = false;
- fGetAddr = false;
- fRelayTxes = false;
- setInventoryKnown.max_size(SendBufferSize() / 1000);
- pfilter = new CBloomFilter();
- nPingNonceSent = 0;
- nPingUsecStart = 0;
- nPingUsecTime = 0;
- fPingQueued = false;
-
- {
- LOCK(cs_nLastNodeId);
- id = nLastNodeId++;
- }
-
- if (fLogIPs)
- LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
- else
- LogPrint("net", "Added connection peer=%d\n", id);
-
- // Be shy and don't send version until we hear
- if (hSocket != INVALID_SOCKET && !fInbound)
- PushVersion();
-
- GetNodeSignals().InitializeNode(GetId(), this);
- }
-
- ~CNode()
- {
- CloseSocket(hSocket);
-
- if (pfilter)
- delete pfilter;
-
- GetNodeSignals().FinalizeNode(GetId());
- }
+ CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false);
+ ~CNode();
private:
// Network usage totals
@@ -452,96 +391,16 @@ public:
}
}
- void AskFor(const CInv& inv)
- {
- // We're using mapAskFor as a priority queue,
- // the key is the earliest time the request can be sent
- int64_t nRequestTime;
- limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
- if (it != mapAlreadyAskedFor.end())
- nRequestTime = it->second;
- else
- nRequestTime = 0;
- LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id);
-
- // Make sure not to reuse time indexes to keep things in the same order
- int64_t nNow = GetTimeMicros() - 1000000;
- static int64_t nLastTime;
- ++nLastTime;
- nNow = std::max(nNow, nLastTime);
- nLastTime = nNow;
-
- // Each retry is 2 minutes after the last
- nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
- if (it != mapAlreadyAskedFor.end())
- mapAlreadyAskedFor.update(it, nRequestTime);
- else
- mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
- mapAskFor.insert(std::make_pair(nRequestTime, inv));
- }
-
-
+ void AskFor(const CInv& inv);
// TODO: Document the postcondition of this function. Is cs_vSend locked?
- void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend)
- {
- ENTER_CRITICAL_SECTION(cs_vSend);
- assert(ssSend.size() == 0);
- ssSend << CMessageHeader(pszCommand, 0);
- LogPrint("net", "sending: %s ", pszCommand);
- }
+ void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend);
// TODO: Document the precondition of this function. Is cs_vSend locked?
- void AbortMessage() UNLOCK_FUNCTION(cs_vSend)
- {
- ssSend.clear();
-
- LEAVE_CRITICAL_SECTION(cs_vSend);
-
- LogPrint("net", "(aborted)\n");
- }
+ void AbortMessage() UNLOCK_FUNCTION(cs_vSend);
// TODO: Document the precondition of this function. Is cs_vSend locked?
- void EndMessage() UNLOCK_FUNCTION(cs_vSend)
- {
- // The -*messagestest options are intentionally not documented in the help message,
- // since they are only used during development to debug the networking code and are
- // not intended for end-users.
- if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
- {
- LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
- AbortMessage();
- return;
- }
- if (mapArgs.count("-fuzzmessagestest"))
- Fuzz(GetArg("-fuzzmessagestest", 10));
-
- if (ssSend.size() == 0)
- return;
-
- // Set the size
- unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
- memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize));
-
- // Set the checksum
- uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
- unsigned int nChecksum = 0;
- memcpy(&nChecksum, &hash, sizeof(nChecksum));
- assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
- memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
-
- LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
-
- std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
- ssSend.GetAndClear(*it);
- nSendSize += (*it).size();
-
- // If write queue empty, attempt "optimistic write"
- if (it == vSendMsg.begin())
- SocketSendData(this);
-
- LEAVE_CRITICAL_SECTION(cs_vSend);
- }
+ void EndMessage() UNLOCK_FUNCTION(cs_vSend);
void PushVersion();
diff --git a/src/netbase.cpp b/src/netbase.cpp
index e9207da330..d5821d4465 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -13,6 +13,7 @@
#include "sync.h"
#include "uint256.h"
#include "util.h"
+#include "utilstrencodings.h"
#ifdef HAVE_GETADDRINFO_A
#include <netdb.h>
@@ -27,6 +28,7 @@
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
+#include <boost/thread.hpp>
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
diff --git a/src/noui.cpp b/src/noui.cpp
index 32c861b0d9..8b00fd4057 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -8,6 +8,7 @@
#include "ui_interface.h"
#include "util.h"
+#include <cstdio>
#include <stdint.h>
#include <string>
diff --git a/src/pow.cpp b/src/pow.cpp
index c0d0a7ca20..b091cbec3d 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -9,6 +9,7 @@
#include "core.h"
#include "main.h"
#include "uint256.h"
+#include "util.h"
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
{
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index a43e7cb756..12277a8ad0 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <boost/filesystem/operations.hpp>
+#include <boost/thread.hpp>
#include <QApplication>
#include <QDebug>
#include <QLibraryInfo>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index bfca5e8d1a..d0a5ff13c3 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -24,6 +24,7 @@
#endif
#include "init.h"
+#include "util.h"
#include "ui_interface.h"
#include <iostream>
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 4c21eb5594..9c9ff5b3a1 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -13,6 +13,7 @@
#include "main.h"
#include "net.h"
#include "ui_interface.h"
+#include "util.h"
#include <stdint.h>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index fd1d446f9b..c775a7f8d6 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -21,6 +21,7 @@
#include "wallet.h" // for CWallet::minTxFee
#endif
+#include <boost/thread.hpp>
#include <QDir>
#include <QIntValidator>
#include <QLocale>
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index a9f1566d62..f6a4b599de 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -11,6 +11,7 @@
#include "base58.h"
#include "ui_interface.h"
+#include "util.h"
#include "wallet.h"
#include <cstdlib>
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 4f6e3169f5..8258e719a3 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -15,6 +15,7 @@
#include "transactionrecord.h"
#include "timedata.h"
#include "ui_interface.h"
+#include "util.h"
#include "wallet.h"
#include <stdint.h>
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 5fb0da145d..7df9d1bc2d 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -10,9 +10,10 @@
#include "clientmodel.h"
#include "guiutil.h"
-#include "clientversion.h"
#include "init.h"
-#include "util.h"
+#include "version.h"
+
+#include <stdio.h>
#include <QLabel>
#include <QRegExp>
diff --git a/src/random.cpp b/src/random.cpp
index 0d20d205ac..22c942acc0 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -8,12 +8,14 @@
#ifdef WIN32
#include "compat.h" // for Windows API
#endif
+#include "serialize.h" // for begin_ptr(vec)
#include "util.h" // for LogPrint()
+#include "utilstrencodings.h" // for GetTime()
#ifndef WIN32
#include <sys/time.h>
#endif
-
+#include <limits>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index e511fe4222..58cab14045 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -7,6 +7,7 @@
#include "main.h"
#include "rpcserver.h"
#include "sync.h"
+#include "util.h"
#include <stdint.h>
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index ff2361482b..e68ddee040 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -7,6 +7,8 @@
#include "init.h"
#include "main.h"
#include "sync.h"
+#include "utiltime.h"
+#include "util.h"
#include "wallet.h"
#include <fstream>
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index edab427cbf..6e508abcda 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -11,6 +11,7 @@
#include "miner.h"
#include "pow.h"
#include "core_io.h"
+#include "util.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp
index 643208b3b6..808b9bbd2a 100644
--- a/src/rpcprotocol.cpp
+++ b/src/rpcprotocol.cpp
@@ -6,6 +6,10 @@
#include "rpcprotocol.h"
#include "util.h"
+#include "tinyformat.h"
+#include "utilstrencodings.h"
+#include "utiltime.h"
+#include "version.h"
#include <stdint.h>
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 524627e2de..c9133bd3d2 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -23,6 +23,7 @@
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
#include "json/json_spirit_writer_template.h"
using namespace boost;
@@ -82,6 +83,11 @@ void RPCTypeCheck(const Object& o,
}
}
+static inline int64_t roundint64(double d)
+{
+ return (int64_t)(d > 0 ? d + 0.5 : d - 0.5);
+}
+
int64_t AmountFromValue(const Value& value)
{
double dAmount = value.get_real();
diff --git a/src/script.cpp b/src/script.cpp
index d6d6684f44..28c50a1358 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -18,8 +18,9 @@
#include "util.h"
#include <boost/foreach.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/tuple/tuple.hpp>
using namespace std;
using namespace boost;
diff --git a/src/script.h b/src/script.h
index 1e2cc94efe..462e3f2302 100644
--- a/src/script.h
+++ b/src/script.h
@@ -7,7 +7,8 @@
#define H_BITCOIN_SCRIPT
#include "key.h"
-#include "util.h"
+#include "utilstrencodings.h"
+#include "tinyformat.h"
#include <stdexcept>
#include <stdint.h>
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 5e17555e7a..4ecf6e2535 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -14,6 +14,7 @@
#include "pow.h"
#include "script.h"
#include "serialize.h"
+#include "util.h"
#include <stdint.h>
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index e3066a51ab..4af87cf8ef 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -11,6 +11,7 @@
#include "serialize.h"
#include "util.h"
+#include "utilstrencodings.h"
#include "version.h"
#include <fstream>
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
index 2752a0b215..69888da3df 100644
--- a/src/test/allocator_tests.cpp
+++ b/src/test/allocator_tests.cpp
@@ -4,6 +4,8 @@
#include "util.h"
+#include "allocators.h"
+
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(allocator_tests)
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index 87473585e3..68617abbdd 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "util.h"
+#include "utilstrencodings.h"
#include <boost/test/unit_test.hpp>
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index d4a23d9aa0..f2bf3326ad 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "util.h"
+#include "utilstrencodings.h"
#include <boost/test/unit_test.hpp>
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
index 10352240f4..fdea12846a 100644
--- a/src/test/checkblock_tests.cpp
+++ b/src/test/checkblock_tests.cpp
@@ -9,6 +9,7 @@
#include "main.h"
+#include "utiltime.h"
#include <cstdio>
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index a17278b803..a3eec270ee 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -6,7 +6,7 @@
#include "crypto/sha1.h"
#include "crypto/sha2.h"
#include "random.h"
-#include "util.h"
+#include "utilstrencodings.h"
#include <vector>
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index 4568c8769b..b8e290f071 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "hash.h"
-#include "util.h"
+#include "utilstrencodings.h"
#include <vector>
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 443b5853b2..68fad8d038 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -16,6 +16,7 @@
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
CClientUIInterface uiInterface;
CWallet* pwalletMain;
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
new file mode 100644
index 0000000000..aa4fa0d500
--- /dev/null
+++ b/src/test/timedata_tests.cpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2011-2014 The Bitcoin Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+#include "timedata.h"
+
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(timedata_tests)
+
+BOOST_AUTO_TEST_CASE(util_MedianFilter)
+{
+ CMedianFilter<int> filter(5, 15);
+
+ BOOST_CHECK_EQUAL(filter.median(), 15);
+
+ filter.input(20); // [15 20]
+ BOOST_CHECK_EQUAL(filter.median(), 17);
+
+ filter.input(30); // [15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 20);
+
+ filter.input(3); // [3 15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 17);
+
+ filter.input(7); // [3 7 15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 15);
+
+ filter.input(18); // [3 7 18 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 18);
+
+ filter.input(0); // [0 3 7 18 30]
+ BOOST_CHECK_EQUAL(filter.median(), 7);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 068b9f29c8..e077c9de3b 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -4,8 +4,11 @@
#include "util.h"
+#include "core.h"
#include "random.h"
#include "sync.h"
+#include "utilstrencodings.h"
+#include "utilmoneystr.h"
#include <stdint.h>
#include <vector>
@@ -36,31 +39,6 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
} while(0);
}
-BOOST_AUTO_TEST_CASE(util_MedianFilter)
-{
- CMedianFilter<int> filter(5, 15);
-
- BOOST_CHECK_EQUAL(filter.median(), 15);
-
- filter.input(20); // [15 20]
- BOOST_CHECK_EQUAL(filter.median(), 17);
-
- filter.input(30); // [15 20 30]
- BOOST_CHECK_EQUAL(filter.median(), 20);
-
- filter.input(3); // [3 15 20 30]
- BOOST_CHECK_EQUAL(filter.median(), 17);
-
- filter.input(7); // [3 7 15 20 30]
- BOOST_CHECK_EQUAL(filter.median(), 15);
-
- filter.input(18); // [3 7 18 20 30]
- BOOST_CHECK_EQUAL(filter.median(), 18);
-
- filter.input(0); // [0 3 7 18 30]
- BOOST_CHECK_EQUAL(filter.median(), 7);
-}
-
static const unsigned char ParseHex_expected[65] = {
0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
diff --git a/src/timedata.cpp b/src/timedata.cpp
index 4576786b96..40cdb33f7a 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -8,6 +8,7 @@
#include "sync.h"
#include "ui_interface.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <boost/foreach.hpp>
@@ -35,6 +36,11 @@ int64_t GetAdjustedTime()
return GetTime() + GetTimeOffset();
}
+static int64_t abs64(int64_t n)
+{
+ return (n >= 0 ? n : -n);
+}
+
void AddTimeData(const CNetAddr& ip, int64_t nTime)
{
int64_t nOffsetSample = nTime - GetTime();
diff --git a/src/timedata.h b/src/timedata.h
index 0e7bdc2c1f..d0c84b3183 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -6,9 +6,68 @@
#define BITCOIN_TIMEDATA_H
#include <stdint.h>
+#include <vector>
+#include <algorithm>
+#include <assert.h>
class CNetAddr;
+/** Median filter over a stream of values.
+ * Returns the median of the last N numbers
+ */
+template <typename T> class CMedianFilter
+{
+private:
+ std::vector<T> vValues;
+ std::vector<T> vSorted;
+ unsigned int nSize;
+public:
+ CMedianFilter(unsigned int size, T initial_value):
+ nSize(size)
+ {
+ vValues.reserve(size);
+ vValues.push_back(initial_value);
+ vSorted = vValues;
+ }
+
+ void input(T value)
+ {
+ if(vValues.size() == nSize)
+ {
+ vValues.erase(vValues.begin());
+ }
+ vValues.push_back(value);
+
+ vSorted.resize(vValues.size());
+ std::copy(vValues.begin(), vValues.end(), vSorted.begin());
+ std::sort(vSorted.begin(), vSorted.end());
+ }
+
+ T median() const
+ {
+ int size = vSorted.size();
+ assert(size>0);
+ if(size & 1) // Odd number of elements
+ {
+ return vSorted[size/2];
+ }
+ else // Even number of elements
+ {
+ return (vSorted[size/2-1] + vSorted[size/2]) / 2;
+ }
+ }
+
+ int size() const
+ {
+ return vValues.size();
+ }
+
+ std::vector<T> sorted () const
+ {
+ return vSorted;
+ }
+};
+
/* Functions to keep track of adjusted P2P time */
int64_t GetTimeOffset();
int64_t GetAdjustedTime();
diff --git a/src/tinyformat.h b/src/tinyformat.h
index 929cb66e4d..73d49a1fe4 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -121,6 +121,7 @@ namespace tfm = tinyformat;
#include <cassert>
#include <iostream>
#include <sstream>
+#include <stdexcept>
#ifndef TINYFORMAT_ERROR
# define TINYFORMAT_ERROR(reason) assert(0 && reason)
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 2349514def..d4c6007558 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -9,6 +9,7 @@
#include "pow.h"
#include "uint256.h"
+#include <boost/thread.hpp>
#include <stdint.h>
using namespace std;
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index f75e2212d5..8af1f1c91b 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -5,6 +5,7 @@
#include "core.h"
#include "txmempool.h"
+#include "util.h"
#include <boost/circular_buffer.hpp>
diff --git a/src/uint256.cpp b/src/uint256.cpp
index 08c05594fd..feda0ca5a9 100644
--- a/src/uint256.cpp
+++ b/src/uint256.cpp
@@ -4,7 +4,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "uint256.h"
-#include "util.h"
+
+#include "utilstrencodings.h"
#include <stdio.h>
#include <string.h>
diff --git a/src/util.cpp b/src/util.cpp
index ae2145a3a0..5a4e187f9e 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -11,14 +11,13 @@
#include "chainparamsbase.h"
#include "random.h"
+#include "serialize.h"
#include "sync.h"
-#include "uint256.h"
-#include "version.h"
+#include "utilstrencodings.h"
+#include "utiltime.h"
#include <stdarg.h>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
#ifndef WIN32
// for posix_fallocate
#ifdef __linux__
@@ -76,6 +75,7 @@
#include <boost/foreach.hpp>
#include <boost/program_options/detail/config_file.hpp>
#include <boost/program_options/parsers.hpp>
+#include <boost/thread.hpp>
#include <openssl/crypto.h>
#include <openssl/rand.h>
@@ -244,148 +244,6 @@ int LogPrintStr(const std::string &str)
return ret;
}
-string FormatMoney(int64_t n, bool fPlus)
-{
- // Note: not using straight sprintf here because we do NOT want
- // localized number formatting.
- int64_t n_abs = (n > 0 ? n : -n);
- int64_t quotient = n_abs/COIN;
- int64_t remainder = n_abs%COIN;
- string str = strprintf("%d.%08d", quotient, remainder);
-
- // Right-trim excess zeros before the decimal point:
- int nTrim = 0;
- for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
- ++nTrim;
- if (nTrim)
- str.erase(str.size()-nTrim, nTrim);
-
- if (n < 0)
- str.insert((unsigned int)0, 1, '-');
- else if (fPlus && n > 0)
- str.insert((unsigned int)0, 1, '+');
- return str;
-}
-
-
-bool ParseMoney(const string& str, int64_t& nRet)
-{
- return ParseMoney(str.c_str(), nRet);
-}
-
-bool ParseMoney(const char* pszIn, int64_t& nRet)
-{
- string strWhole;
- int64_t nUnits = 0;
- const char* p = pszIn;
- while (isspace(*p))
- p++;
- for (; *p; p++)
- {
- if (*p == '.')
- {
- p++;
- int64_t nMult = CENT*10;
- while (isdigit(*p) && (nMult > 0))
- {
- nUnits += nMult * (*p++ - '0');
- nMult /= 10;
- }
- break;
- }
- if (isspace(*p))
- break;
- if (!isdigit(*p))
- return false;
- strWhole.insert(strWhole.end(), *p);
- }
- for (; *p; p++)
- if (!isspace(*p))
- return false;
- if (strWhole.size() > 10) // guard against 63 bit overflow
- return false;
- if (nUnits < 0 || nUnits > COIN)
- return false;
- int64_t nWhole = atoi64(strWhole);
- int64_t nValue = nWhole*COIN + nUnits;
-
- nRet = nValue;
- return true;
-}
-
-// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
-// even possibly remotely dangerous like & or >
-static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@");
-string SanitizeString(const string& str)
-{
- string strResult;
- for (std::string::size_type i = 0; i < str.size(); i++)
- {
- if (safeChars.find(str[i]) != std::string::npos)
- strResult.push_back(str[i]);
- }
- return strResult;
-}
-
-const signed char p_util_hexdigit[256] =
-{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
- -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
-
-signed char HexDigit(char c)
-{
- return p_util_hexdigit[(unsigned char)c];
-}
-
-bool IsHex(const string& str)
-{
- BOOST_FOREACH(char c, str)
- {
- if (HexDigit(c) < 0)
- return false;
- }
- return (str.size() > 0) && (str.size()%2 == 0);
-}
-
-vector<unsigned char> ParseHex(const char* psz)
-{
- // convert hex dump to vector
- vector<unsigned char> vch;
- while (true)
- {
- while (isspace(*psz))
- psz++;
- signed char c = HexDigit(*psz++);
- if (c == (signed char)-1)
- break;
- unsigned char n = (c << 4);
- c = HexDigit(*psz++);
- if (c == (signed char)-1)
- break;
- n |= c;
- vch.push_back(n);
- }
- return vch;
-}
-
-vector<unsigned char> ParseHex(const string& str)
-{
- return ParseHex(str.c_str());
-}
-
static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
{
// interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
@@ -483,334 +341,6 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue)
return SoftSetArg(strArg, std::string("0"));
}
-
-string EncodeBase64(const unsigned char* pch, size_t len)
-{
- static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- string strRet="";
- strRet.reserve((len+2)/3*4);
-
- int mode=0, left=0;
- const unsigned char *pchEnd = pch+len;
-
- while (pch<pchEnd)
- {
- int enc = *(pch++);
- switch (mode)
- {
- case 0: // we have no bits
- strRet += pbase64[enc >> 2];
- left = (enc & 3) << 4;
- mode = 1;
- break;
-
- case 1: // we have two bits
- strRet += pbase64[left | (enc >> 4)];
- left = (enc & 15) << 2;
- mode = 2;
- break;
-
- case 2: // we have four bits
- strRet += pbase64[left | (enc >> 6)];
- strRet += pbase64[enc & 63];
- mode = 0;
- break;
- }
- }
-
- if (mode)
- {
- strRet += pbase64[left];
- strRet += '=';
- if (mode == 1)
- strRet += '=';
- }
-
- return strRet;
-}
-
-string EncodeBase64(const string& str)
-{
- return EncodeBase64((const unsigned char*)str.c_str(), str.size());
-}
-
-vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
-{
- static const int decode64_table[256] =
- {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
- -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- };
-
- if (pfInvalid)
- *pfInvalid = false;
-
- vector<unsigned char> vchRet;
- vchRet.reserve(strlen(p)*3/4);
-
- int mode = 0;
- int left = 0;
-
- while (1)
- {
- int dec = decode64_table[(unsigned char)*p];
- if (dec == -1) break;
- p++;
- switch (mode)
- {
- case 0: // we have no bits and get 6
- left = dec;
- mode = 1;
- break;
-
- case 1: // we have 6 bits and keep 4
- vchRet.push_back((left<<2) | (dec>>4));
- left = dec & 15;
- mode = 2;
- break;
-
- case 2: // we have 4 bits and get 6, we keep 2
- vchRet.push_back((left<<4) | (dec>>2));
- left = dec & 3;
- mode = 3;
- break;
-
- case 3: // we have 2 bits and get 6
- vchRet.push_back((left<<6) | dec);
- mode = 0;
- break;
- }
- }
-
- if (pfInvalid)
- switch (mode)
- {
- case 0: // 4n base64 characters processed: ok
- break;
-
- case 1: // 4n+1 base64 character processed: impossible
- *pfInvalid = true;
- break;
-
- case 2: // 4n+2 base64 characters processed: require '=='
- if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
- *pfInvalid = true;
- break;
-
- case 3: // 4n+3 base64 characters processed: require '='
- if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
- *pfInvalid = true;
- break;
- }
-
- return vchRet;
-}
-
-string DecodeBase64(const string& str)
-{
- vector<unsigned char> vchRet = DecodeBase64(str.c_str());
- return string((const char*)&vchRet[0], vchRet.size());
-}
-
-string EncodeBase32(const unsigned char* pch, size_t len)
-{
- static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
-
- string strRet="";
- strRet.reserve((len+4)/5*8);
-
- int mode=0, left=0;
- const unsigned char *pchEnd = pch+len;
-
- while (pch<pchEnd)
- {
- int enc = *(pch++);
- switch (mode)
- {
- case 0: // we have no bits
- strRet += pbase32[enc >> 3];
- left = (enc & 7) << 2;
- mode = 1;
- break;
-
- case 1: // we have three bits
- strRet += pbase32[left | (enc >> 6)];
- strRet += pbase32[(enc >> 1) & 31];
- left = (enc & 1) << 4;
- mode = 2;
- break;
-
- case 2: // we have one bit
- strRet += pbase32[left | (enc >> 4)];
- left = (enc & 15) << 1;
- mode = 3;
- break;
-
- case 3: // we have four bits
- strRet += pbase32[left | (enc >> 7)];
- strRet += pbase32[(enc >> 2) & 31];
- left = (enc & 3) << 3;
- mode = 4;
- break;
-
- case 4: // we have two bits
- strRet += pbase32[left | (enc >> 5)];
- strRet += pbase32[enc & 31];
- mode = 0;
- }
- }
-
- static const int nPadding[5] = {0, 6, 4, 3, 1};
- if (mode)
- {
- strRet += pbase32[left];
- for (int n=0; n<nPadding[mode]; n++)
- strRet += '=';
- }
-
- return strRet;
-}
-
-string EncodeBase32(const string& str)
-{
- return EncodeBase32((const unsigned char*)str.c_str(), str.size());
-}
-
-vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
-{
- static const int decode32_table[256] =
- {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
- };
-
- if (pfInvalid)
- *pfInvalid = false;
-
- vector<unsigned char> vchRet;
- vchRet.reserve((strlen(p))*5/8);
-
- int mode = 0;
- int left = 0;
-
- while (1)
- {
- int dec = decode32_table[(unsigned char)*p];
- if (dec == -1) break;
- p++;
- switch (mode)
- {
- case 0: // we have no bits and get 5
- left = dec;
- mode = 1;
- break;
-
- case 1: // we have 5 bits and keep 2
- vchRet.push_back((left<<3) | (dec>>2));
- left = dec & 3;
- mode = 2;
- break;
-
- case 2: // we have 2 bits and keep 7
- left = left << 5 | dec;
- mode = 3;
- break;
-
- case 3: // we have 7 bits and keep 4
- vchRet.push_back((left<<1) | (dec>>4));
- left = dec & 15;
- mode = 4;
- break;
-
- case 4: // we have 4 bits, and keep 1
- vchRet.push_back((left<<4) | (dec>>1));
- left = dec & 1;
- mode = 5;
- break;
-
- case 5: // we have 1 bit, and keep 6
- left = left << 5 | dec;
- mode = 6;
- break;
-
- case 6: // we have 6 bits, and keep 3
- vchRet.push_back((left<<2) | (dec>>3));
- left = dec & 7;
- mode = 7;
- break;
-
- case 7: // we have 3 bits, and keep 0
- vchRet.push_back((left<<5) | dec);
- mode = 0;
- break;
- }
- }
-
- if (pfInvalid)
- switch (mode)
- {
- case 0: // 8n base32 characters processed: ok
- break;
-
- case 1: // 8n+1 base32 characters processed: impossible
- case 3: // +3
- case 6: // +6
- *pfInvalid = true;
- break;
-
- case 2: // 8n+2 base32 characters processed: require '======'
- if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1)
- *pfInvalid = true;
- break;
-
- case 4: // 8n+4 base32 characters processed: require '===='
- if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1)
- *pfInvalid = true;
- break;
-
- case 5: // 8n+5 base32 characters processed: require '==='
- if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1)
- *pfInvalid = true;
- break;
-
- case 7: // 8n+7 base32 characters processed: require '='
- if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1)
- *pfInvalid = true;
- break;
- }
-
- return vchRet;
-}
-
-string DecodeBase32(const string& str)
-{
- vector<unsigned char> vchRet = DecodeBase32(str.c_str());
- return string((const char*)&vchRet[0], vchRet.size());
-}
-
static std::string FormatException(std::exception* pex, const char* pszThread)
{
#ifdef WIN32
@@ -1102,45 +632,6 @@ void ShrinkDebugFile()
fclose(file);
}
-static int64_t nMockTime = 0; // For unit testing
-
-int64_t GetTime()
-{
- if (nMockTime) return nMockTime;
-
- return time(NULL);
-}
-
-void SetMockTime(int64_t nMockTimeIn)
-{
- nMockTime = nMockTimeIn;
-}
-
-string FormatVersion(int nVersion)
-{
- if (nVersion%100 == 0)
- return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
- else
- return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
-}
-
-string FormatFullVersion()
-{
- return CLIENT_BUILD;
-}
-
-// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
-std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
-{
- std::ostringstream ss;
- ss << "/";
- ss << name << ":" << FormatVersion(nClientVersion);
- if (!comments.empty())
- ss << "(" << boost::algorithm::join(comments, "; ") << ")";
- ss << "/";
- return ss.str();
-}
-
#ifdef WIN32
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
{
@@ -1211,20 +702,6 @@ void RenameThread(const char* name)
#endif
}
-bool ParseInt32(const std::string& str, int32_t *out)
-{
- char *endp = NULL;
- errno = 0; // strtol will not set errno if valid
- long int n = strtol(str.c_str(), &endp, 10);
- if(out) *out = (int)n;
- // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
- // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
- // platforms the size of these types may be different.
- return endp && *endp == 0 && !errno &&
- n >= std::numeric_limits<int32_t>::min() &&
- n <= std::numeric_limits<int32_t>::max();
-}
-
void SetupEnvironment()
{
#ifndef WIN32
@@ -1242,47 +719,15 @@ void SetupEnvironment()
#endif
}
-std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
+void SetThreadPriority(int nPriority)
{
- // std::locale takes ownership of the pointer
- std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
- std::stringstream ss;
- ss.imbue(loc);
- 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();
+#ifdef WIN32
+ SetThreadPriority(GetCurrentThread(), nPriority);
+#else // WIN32
+#ifdef PRIO_THREAD
+ setpriority(PRIO_THREAD, 0, nPriority);
+#else // PRIO_THREAD
+ setpriority(PRIO_PROCESS, 0, nPriority);
+#endif // PRIO_THREAD
+#endif // WIN32
}
diff --git a/src/util.h b/src/util.h
index 1fb42a7b7e..30f7c15c89 100644
--- a/src/util.h
+++ b/src/util.h
@@ -3,6 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+/**
+ * Server/client environment: argument handling, config file parsing,
+ * logging, thread wrappers
+ */
#ifndef BITCOIN_UTIL_H
#define BITCOIN_UTIL_H
@@ -11,84 +15,17 @@
#endif
#include "compat.h"
-#include "serialize.h"
+#include "utiltime.h"
#include "tinyformat.h"
-#include <cstdio>
#include <exception>
#include <map>
-#include <stdarg.h>
#include <stdint.h>
#include <string>
-#include <utility>
#include <vector>
-#ifndef WIN32
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#endif
-
#include <boost/filesystem/path.hpp>
-#include <boost/thread.hpp>
-
-class uint256;
-
-static const int64_t COIN = 100000000;
-static const int64_t CENT = 1000000;
-
-#define BEGIN(a) ((char*)&(a))
-#define END(a) ((char*)&((&(a))[1]))
-#define UBEGIN(a) ((unsigned char*)&(a))
-#define UEND(a) ((unsigned char*)&((&(a))[1]))
-#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
-
-// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
-#define PAIRTYPE(t1, t2) std::pair<t1, t2>
-
-// Align by increasing pointer, must have extra space at end of buffer
-template <size_t nBytes, typename T>
-T* alignup(T* p)
-{
- union
- {
- T* ptr;
- size_t n;
- } u;
- u.ptr = p;
- u.n = (u.n + (nBytes-1)) & ~(nBytes-1);
- return u.ptr;
-}
-
-#ifdef WIN32
-#define MSG_DONTWAIT 0
-
-#ifndef S_IRUSR
-#define S_IRUSR 0400
-#define S_IWUSR 0200
-#endif
-#else
-#define MAX_PATH 1024
-#endif
-// As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0
-#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
-#define MSG_NOSIGNAL 0
-#endif
-
-inline void MilliSleep(int64_t n)
-{
-// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
-// until fixed in 1.52. Use the deprecated sleep method for the broken case.
-// See: https://svn.boost.org/trac/boost/ticket/7238
-#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
- boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
-#elif defined(HAVE_WORKING_BOOST_SLEEP)
- boost::this_thread::sleep(boost::posix_time::milliseconds(n));
-#else
-//should never get here
-#error missing boost sleep implementation
-#endif
-}
+#include <boost/thread/exceptions.hpp>
extern std::map<std::string, std::string> mapArgs;
extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
@@ -146,22 +83,6 @@ static inline bool error(const char* format)
}
void PrintExceptionContinue(std::exception* pex, const char* pszThread);
-std::string FormatMoney(int64_t n, bool fPlus=false);
-bool ParseMoney(const std::string& str, int64_t& nRet);
-bool ParseMoney(const char* pszIn, int64_t& nRet);
-std::string SanitizeString(const std::string& str);
-std::vector<unsigned char> ParseHex(const char* psz);
-std::vector<unsigned char> ParseHex(const std::string& str);
-signed char HexDigit(char c);
-bool IsHex(const std::string& str);
-std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
-std::string DecodeBase64(const std::string& str);
-std::string EncodeBase64(const unsigned char* pch, size_t len);
-std::string EncodeBase64(const std::string& str);
-std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
-std::string DecodeBase32(const std::string& str);
-std::string EncodeBase32(const unsigned char* pch, size_t len);
-std::string EncodeBase32(const std::string& str);
void ParseParameters(int argc, const char*const argv[]);
void FileCommit(FILE *fileout);
bool TruncateFile(FILE *file, unsigned int length);
@@ -182,111 +103,8 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
boost::filesystem::path GetTempPath();
void ShrinkDebugFile();
-int64_t GetTime();
-void SetMockTime(int64_t nMockTimeIn);
-std::string FormatFullVersion();
-std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
void runCommand(std::string strCommand);
-inline std::string i64tostr(int64_t n)
-{
- return strprintf("%d", n);
-}
-
-inline std::string itostr(int n)
-{
- return strprintf("%d", n);
-}
-
-inline int64_t atoi64(const char* psz)
-{
-#ifdef _MSC_VER
- return _atoi64(psz);
-#else
- return strtoll(psz, NULL, 10);
-#endif
-}
-
-inline int64_t atoi64(const std::string& str)
-{
-#ifdef _MSC_VER
- return _atoi64(str.c_str());
-#else
- return strtoll(str.c_str(), NULL, 10);
-#endif
-}
-
-inline int atoi(const std::string& str)
-{
- return atoi(str.c_str());
-}
-
-/**
- * Convert string to signed 32-bit integer with strict parse error feedback.
- * @returns true if the entire string could be parsed as valid integer,
- * false if not the entire string could be parsed or when overflow or underflow occured.
- */
-bool ParseInt32(const std::string& str, int32_t *out);
-
-inline int roundint(double d)
-{
- return (int)(d > 0 ? d + 0.5 : d - 0.5);
-}
-
-inline int64_t roundint64(double d)
-{
- return (int64_t)(d > 0 ? d + 0.5 : d - 0.5);
-}
-
-inline int64_t abs64(int64_t n)
-{
- return (n >= 0 ? n : -n);
-}
-
-template<typename T>
-std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
-{
- std::string rv;
- static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- rv.reserve((itend-itbegin)*3);
- for(T it = itbegin; it < itend; ++it)
- {
- unsigned char val = (unsigned char)(*it);
- if(fSpaces && it != itbegin)
- rv.push_back(' ');
- rv.push_back(hexmap[val>>4]);
- rv.push_back(hexmap[val&15]);
- }
-
- return rv;
-}
-
-template<typename T>
-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 GetTimeMillis()
-{
- return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
- boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
-}
-
-inline int64_t GetTimeMicros()
-{
- return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
- boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
-}
-
-std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime);
-
inline bool IsSwitchChar(char c)
{
#ifdef WIN32
@@ -341,113 +159,9 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue);
*/
bool SoftSetBoolArg(const std::string& strArg, bool fValue);
-/**
- * Timing-attack-resistant comparison.
- * Takes time proportional to length
- * of first argument.
- */
-template <typename T>
-bool TimingResistantEqual(const T& a, const T& b)
-{
- if (b.size() == 0) return a.size() == 0;
- size_t accumulator = a.size() ^ b.size();
- for (size_t i = 0; i < a.size(); i++)
- accumulator |= a[i] ^ b[i%b.size()];
- return accumulator == 0;
-}
-
-/** Median filter over a stream of values.
- * Returns the median of the last N numbers
- */
-template <typename T> class CMedianFilter
-{
-private:
- std::vector<T> vValues;
- std::vector<T> vSorted;
- unsigned int nSize;
-public:
- CMedianFilter(unsigned int size, T initial_value):
- nSize(size)
- {
- vValues.reserve(size);
- vValues.push_back(initial_value);
- vSorted = vValues;
- }
-
- void input(T value)
- {
- if(vValues.size() == nSize)
- {
- vValues.erase(vValues.begin());
- }
- vValues.push_back(value);
-
- vSorted.resize(vValues.size());
- std::copy(vValues.begin(), vValues.end(), vSorted.begin());
- std::sort(vSorted.begin(), vSorted.end());
- }
-
- T median() const
- {
- int size = vSorted.size();
- assert(size>0);
- if(size & 1) // Odd number of elements
- {
- return vSorted[size/2];
- }
- else // Even number of elements
- {
- return (vSorted[size/2-1] + vSorted[size/2]) / 2;
- }
- }
-
- int size() const
- {
- return vValues.size();
- }
-
- std::vector<T> sorted () const
- {
- return vSorted;
- }
-};
-
-#ifdef WIN32
-inline void SetThreadPriority(int nPriority)
-{
- SetThreadPriority(GetCurrentThread(), nPriority);
-}
-#else
-
-// PRIO_MAX is not defined on Solaris
-#ifndef PRIO_MAX
-#define PRIO_MAX 20
-#endif
-#define THREAD_PRIORITY_LOWEST PRIO_MAX
-#define THREAD_PRIORITY_BELOW_NORMAL 2
-#define THREAD_PRIORITY_NORMAL 0
-#define THREAD_PRIORITY_ABOVE_NORMAL (-2)
-
-inline void SetThreadPriority(int nPriority)
-{
- // It's unclear if it's even possible to change thread priorities on Linux,
- // but we really and truly need it for the generation threads.
-#ifdef PRIO_THREAD
- setpriority(PRIO_THREAD, 0, nPriority);
-#else
- setpriority(PRIO_PROCESS, 0, nPriority);
-#endif
-}
-#endif
-
+void SetThreadPriority(int nPriority);
void RenameThread(const char* name);
-inline uint32_t ByteReverse(uint32_t value)
-{
- value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
- return (value<<16) | (value>>16);
-}
-
// Standard wrapper for do-something-forever thread functions.
// "Forever" really means until the thread is interrupted.
// Use it like:
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
new file mode 100644
index 0000000000..1bd48d8d4c
--- /dev/null
+++ b/src/utilmoneystr.cpp
@@ -0,0 +1,75 @@
+#include "utilmoneystr.h"
+
+#include "core.h"
+#include "tinyformat.h"
+
+using namespace std;
+
+string FormatMoney(int64_t n, bool fPlus)
+{
+ // Note: not using straight sprintf here because we do NOT want
+ // localized number formatting.
+ int64_t n_abs = (n > 0 ? n : -n);
+ int64_t quotient = n_abs/COIN;
+ int64_t remainder = n_abs%COIN;
+ string str = strprintf("%d.%08d", quotient, remainder);
+
+ // Right-trim excess zeros before the decimal point:
+ int nTrim = 0;
+ for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
+ ++nTrim;
+ if (nTrim)
+ str.erase(str.size()-nTrim, nTrim);
+
+ if (n < 0)
+ str.insert((unsigned int)0, 1, '-');
+ else if (fPlus && n > 0)
+ str.insert((unsigned int)0, 1, '+');
+ return str;
+}
+
+
+bool ParseMoney(const string& str, int64_t& nRet)
+{
+ return ParseMoney(str.c_str(), nRet);
+}
+
+bool ParseMoney(const char* pszIn, int64_t& nRet)
+{
+ string strWhole;
+ int64_t nUnits = 0;
+ const char* p = pszIn;
+ while (isspace(*p))
+ p++;
+ for (; *p; p++)
+ {
+ if (*p == '.')
+ {
+ p++;
+ int64_t nMult = CENT*10;
+ while (isdigit(*p) && (nMult > 0))
+ {
+ nUnits += nMult * (*p++ - '0');
+ nMult /= 10;
+ }
+ break;
+ }
+ if (isspace(*p))
+ break;
+ if (!isdigit(*p))
+ return false;
+ strWhole.insert(strWhole.end(), *p);
+ }
+ for (; *p; p++)
+ if (!isspace(*p))
+ return false;
+ if (strWhole.size() > 10) // guard against 63 bit overflow
+ return false;
+ if (nUnits < 0 || nUnits > COIN)
+ return false;
+ int64_t nWhole = atoi64(strWhole);
+ int64_t nValue = nWhole*COIN + nUnits;
+
+ nRet = nValue;
+ return true;
+}
diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h
new file mode 100644
index 0000000000..f0c61aa138
--- /dev/null
+++ b/src/utilmoneystr.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/**
+ * Money parsing/formatting utilities.
+ */
+#ifndef BITCOIN_UTILMONEYSTR_H
+#define BITCOIN_UTILMONEYSTR_H
+
+#include <stdint.h>
+#include <string>
+
+std::string FormatMoney(int64_t n, bool fPlus=false);
+bool ParseMoney(const std::string& str, int64_t& nRet);
+bool ParseMoney(const char* pszIn, int64_t& nRet);
+
+#endif // BITCOIN_UTILMONEYSTR_H
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
new file mode 100644
index 0000000000..ef13555104
--- /dev/null
+++ b/src/utilstrencodings.cpp
@@ -0,0 +1,496 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "utilstrencodings.h"
+
+#include "tinyformat.h"
+
+#include <boost/foreach.hpp>
+#include <errno.h>
+#include <limits>
+
+using namespace std;
+
+// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
+// even possibly remotely dangerous like & or >
+static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@");
+string SanitizeString(const string& str)
+{
+ string strResult;
+ for (std::string::size_type i = 0; i < str.size(); i++)
+ {
+ if (safeChars.find(str[i]) != std::string::npos)
+ strResult.push_back(str[i]);
+ }
+ return strResult;
+}
+
+const signed char p_util_hexdigit[256] =
+{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
+ -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
+
+signed char HexDigit(char c)
+{
+ return p_util_hexdigit[(unsigned char)c];
+}
+
+bool IsHex(const string& str)
+{
+ BOOST_FOREACH(char c, str)
+ {
+ if (HexDigit(c) < 0)
+ return false;
+ }
+ return (str.size() > 0) && (str.size()%2 == 0);
+}
+
+vector<unsigned char> ParseHex(const char* psz)
+{
+ // convert hex dump to vector
+ vector<unsigned char> vch;
+ while (true)
+ {
+ while (isspace(*psz))
+ psz++;
+ signed char c = HexDigit(*psz++);
+ if (c == (signed char)-1)
+ break;
+ unsigned char n = (c << 4);
+ c = HexDigit(*psz++);
+ if (c == (signed char)-1)
+ break;
+ n |= c;
+ vch.push_back(n);
+ }
+ return vch;
+}
+
+vector<unsigned char> ParseHex(const string& str)
+{
+ return ParseHex(str.c_str());
+}
+
+string EncodeBase64(const unsigned char* pch, size_t len)
+{
+ static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ string strRet="";
+ strRet.reserve((len+2)/3*4);
+
+ int mode=0, left=0;
+ const unsigned char *pchEnd = pch+len;
+
+ while (pch<pchEnd)
+ {
+ int enc = *(pch++);
+ switch (mode)
+ {
+ case 0: // we have no bits
+ strRet += pbase64[enc >> 2];
+ left = (enc & 3) << 4;
+ mode = 1;
+ break;
+
+ case 1: // we have two bits
+ strRet += pbase64[left | (enc >> 4)];
+ left = (enc & 15) << 2;
+ mode = 2;
+ break;
+
+ case 2: // we have four bits
+ strRet += pbase64[left | (enc >> 6)];
+ strRet += pbase64[enc & 63];
+ mode = 0;
+ break;
+ }
+ }
+
+ if (mode)
+ {
+ strRet += pbase64[left];
+ strRet += '=';
+ if (mode == 1)
+ strRet += '=';
+ }
+
+ return strRet;
+}
+
+string EncodeBase64(const string& str)
+{
+ return EncodeBase64((const unsigned char*)str.c_str(), str.size());
+}
+
+vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
+{
+ static const int decode64_table[256] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
+ -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
+ if (pfInvalid)
+ *pfInvalid = false;
+
+ vector<unsigned char> vchRet;
+ vchRet.reserve(strlen(p)*3/4);
+
+ int mode = 0;
+ int left = 0;
+
+ while (1)
+ {
+ int dec = decode64_table[(unsigned char)*p];
+ if (dec == -1) break;
+ p++;
+ switch (mode)
+ {
+ case 0: // we have no bits and get 6
+ left = dec;
+ mode = 1;
+ break;
+
+ case 1: // we have 6 bits and keep 4
+ vchRet.push_back((left<<2) | (dec>>4));
+ left = dec & 15;
+ mode = 2;
+ break;
+
+ case 2: // we have 4 bits and get 6, we keep 2
+ vchRet.push_back((left<<4) | (dec>>2));
+ left = dec & 3;
+ mode = 3;
+ break;
+
+ case 3: // we have 2 bits and get 6
+ vchRet.push_back((left<<6) | dec);
+ mode = 0;
+ break;
+ }
+ }
+
+ if (pfInvalid)
+ switch (mode)
+ {
+ case 0: // 4n base64 characters processed: ok
+ break;
+
+ case 1: // 4n+1 base64 character processed: impossible
+ *pfInvalid = true;
+ break;
+
+ case 2: // 4n+2 base64 characters processed: require '=='
+ if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
+ *pfInvalid = true;
+ break;
+
+ case 3: // 4n+3 base64 characters processed: require '='
+ if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
+ *pfInvalid = true;
+ break;
+ }
+
+ return vchRet;
+}
+
+string DecodeBase64(const string& str)
+{
+ vector<unsigned char> vchRet = DecodeBase64(str.c_str());
+ return string((const char*)&vchRet[0], vchRet.size());
+}
+
+string EncodeBase32(const unsigned char* pch, size_t len)
+{
+ static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
+
+ string strRet="";
+ strRet.reserve((len+4)/5*8);
+
+ int mode=0, left=0;
+ const unsigned char *pchEnd = pch+len;
+
+ while (pch<pchEnd)
+ {
+ int enc = *(pch++);
+ switch (mode)
+ {
+ case 0: // we have no bits
+ strRet += pbase32[enc >> 3];
+ left = (enc & 7) << 2;
+ mode = 1;
+ break;
+
+ case 1: // we have three bits
+ strRet += pbase32[left | (enc >> 6)];
+ strRet += pbase32[(enc >> 1) & 31];
+ left = (enc & 1) << 4;
+ mode = 2;
+ break;
+
+ case 2: // we have one bit
+ strRet += pbase32[left | (enc >> 4)];
+ left = (enc & 15) << 1;
+ mode = 3;
+ break;
+
+ case 3: // we have four bits
+ strRet += pbase32[left | (enc >> 7)];
+ strRet += pbase32[(enc >> 2) & 31];
+ left = (enc & 3) << 3;
+ mode = 4;
+ break;
+
+ case 4: // we have two bits
+ strRet += pbase32[left | (enc >> 5)];
+ strRet += pbase32[enc & 31];
+ mode = 0;
+ }
+ }
+
+ static const int nPadding[5] = {0, 6, 4, 3, 1};
+ if (mode)
+ {
+ strRet += pbase32[left];
+ for (int n=0; n<nPadding[mode]; n++)
+ strRet += '=';
+ }
+
+ return strRet;
+}
+
+string EncodeBase32(const string& str)
+{
+ return EncodeBase32((const unsigned char*)str.c_str(), str.size());
+}
+
+vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
+{
+ static const int decode32_table[256] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
+ if (pfInvalid)
+ *pfInvalid = false;
+
+ vector<unsigned char> vchRet;
+ vchRet.reserve((strlen(p))*5/8);
+
+ int mode = 0;
+ int left = 0;
+
+ while (1)
+ {
+ int dec = decode32_table[(unsigned char)*p];
+ if (dec == -1) break;
+ p++;
+ switch (mode)
+ {
+ case 0: // we have no bits and get 5
+ left = dec;
+ mode = 1;
+ break;
+
+ case 1: // we have 5 bits and keep 2
+ vchRet.push_back((left<<3) | (dec>>2));
+ left = dec & 3;
+ mode = 2;
+ break;
+
+ case 2: // we have 2 bits and keep 7
+ left = left << 5 | dec;
+ mode = 3;
+ break;
+
+ case 3: // we have 7 bits and keep 4
+ vchRet.push_back((left<<1) | (dec>>4));
+ left = dec & 15;
+ mode = 4;
+ break;
+
+ case 4: // we have 4 bits, and keep 1
+ vchRet.push_back((left<<4) | (dec>>1));
+ left = dec & 1;
+ mode = 5;
+ break;
+
+ case 5: // we have 1 bit, and keep 6
+ left = left << 5 | dec;
+ mode = 6;
+ break;
+
+ case 6: // we have 6 bits, and keep 3
+ vchRet.push_back((left<<2) | (dec>>3));
+ left = dec & 7;
+ mode = 7;
+ break;
+
+ case 7: // we have 3 bits, and keep 0
+ vchRet.push_back((left<<5) | dec);
+ mode = 0;
+ break;
+ }
+ }
+
+ if (pfInvalid)
+ switch (mode)
+ {
+ case 0: // 8n base32 characters processed: ok
+ break;
+
+ case 1: // 8n+1 base32 characters processed: impossible
+ case 3: // +3
+ case 6: // +6
+ *pfInvalid = true;
+ break;
+
+ case 2: // 8n+2 base32 characters processed: require '======'
+ if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1)
+ *pfInvalid = true;
+ break;
+
+ case 4: // 8n+4 base32 characters processed: require '===='
+ if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1)
+ *pfInvalid = true;
+ break;
+
+ case 5: // 8n+5 base32 characters processed: require '==='
+ if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1)
+ *pfInvalid = true;
+ break;
+
+ case 7: // 8n+7 base32 characters processed: require '='
+ if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1)
+ *pfInvalid = true;
+ break;
+ }
+
+ return vchRet;
+}
+
+string DecodeBase32(const string& str)
+{
+ vector<unsigned char> vchRet = DecodeBase32(str.c_str());
+ return string((const char*)&vchRet[0], vchRet.size());
+}
+
+bool ParseInt32(const std::string& str, int32_t *out)
+{
+ char *endp = NULL;
+ errno = 0; // strtol will not set errno if valid
+ long int n = strtol(str.c_str(), &endp, 10);
+ if(out) *out = (int)n;
+ // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
+ // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
+ // platforms the size of these types may be different.
+ return endp && *endp == 0 && !errno &&
+ n >= std::numeric_limits<int32_t>::min() &&
+ n <= std::numeric_limits<int32_t>::max();
+}
+
+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();
+}
+
+std::string i64tostr(int64_t n)
+{
+ return strprintf("%d", n);
+}
+
+std::string itostr(int n)
+{
+ return strprintf("%d", n);
+}
+
+int64_t atoi64(const char* psz)
+{
+#ifdef _MSC_VER
+ return _atoi64(psz);
+#else
+ return strtoll(psz, NULL, 10);
+#endif
+}
+
+int64_t atoi64(const std::string& str)
+{
+#ifdef _MSC_VER
+ return _atoi64(str.c_str());
+#else
+ return strtoll(str.c_str(), NULL, 10);
+#endif
+}
+
+int atoi(const std::string& str)
+{
+ return atoi(str.c_str());
+}
diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h
new file mode 100644
index 0000000000..0b8c1a1781
--- /dev/null
+++ b/src/utilstrencodings.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/**
+ * Utilities for converting data from/to strings.
+ */
+#ifndef BITCOIN_UTILSTRENCODINGS_H
+#define BITCOIN_UTILSTRENCODINGS_H
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#define BEGIN(a) ((char*)&(a))
+#define END(a) ((char*)&((&(a))[1]))
+#define UBEGIN(a) ((unsigned char*)&(a))
+#define UEND(a) ((unsigned char*)&((&(a))[1]))
+#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
+
+// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
+#define PAIRTYPE(t1, t2) std::pair<t1, t2>
+
+std::string SanitizeString(const std::string& str);
+std::vector<unsigned char> ParseHex(const char* psz);
+std::vector<unsigned char> ParseHex(const std::string& str);
+signed char HexDigit(char c);
+bool IsHex(const std::string& str);
+std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
+std::string DecodeBase64(const std::string& str);
+std::string EncodeBase64(const unsigned char* pch, size_t len);
+std::string EncodeBase64(const std::string& str);
+std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
+std::string DecodeBase32(const std::string& str);
+std::string EncodeBase32(const unsigned char* pch, size_t len);
+std::string EncodeBase32(const std::string& str);
+
+std::string i64tostr(int64_t n);
+std::string itostr(int n);
+int64_t atoi64(const char* psz);
+int64_t atoi64(const std::string& str);
+int atoi(const std::string& str);
+
+/**
+ * Convert string to signed 32-bit integer with strict parse error feedback.
+ * @returns true if the entire string could be parsed as valid integer,
+ * false if not the entire string could be parsed or when overflow or underflow occured.
+ */
+bool ParseInt32(const std::string& str, int32_t *out);
+
+template<typename T>
+std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
+{
+ std::string rv;
+ static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ rv.reserve((itend-itbegin)*3);
+ for(T it = itbegin; it < itend; ++it)
+ {
+ unsigned char val = (unsigned char)(*it);
+ if(fSpaces && it != itbegin)
+ rv.push_back(' ');
+ rv.push_back(hexmap[val>>4]);
+ rv.push_back(hexmap[val&15]);
+ }
+
+ return rv;
+}
+
+template<typename T>
+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);
+
+/**
+ * Timing-attack-resistant comparison.
+ * Takes time proportional to length
+ * of first argument.
+ */
+template <typename T>
+bool TimingResistantEqual(const T& a, const T& b)
+{
+ if (b.size() == 0) return a.size() == 0;
+ size_t accumulator = a.size() ^ b.size();
+ for (size_t i = 0; i < a.size(); i++)
+ accumulator |= a[i] ^ b[i%b.size()];
+ return accumulator == 0;
+}
+
+#endif // BITCOIN_UTILSTRENCODINGS_H
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
new file mode 100644
index 0000000000..78f0342cba
--- /dev/null
+++ b/src/utiltime.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
+#include "utiltime.h"
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread.hpp>
+
+using namespace std;
+
+static int64_t nMockTime = 0; // For unit testing
+
+int64_t GetTime()
+{
+ if (nMockTime) return nMockTime;
+
+ return time(NULL);
+}
+
+void SetMockTime(int64_t nMockTimeIn)
+{
+ nMockTime = nMockTimeIn;
+}
+
+int64_t GetTimeMillis()
+{
+ return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
+ boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
+}
+
+int64_t GetTimeMicros()
+{
+ return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
+ boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
+}
+
+void MilliSleep(int64_t n)
+{
+// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
+// until fixed in 1.52. Use the deprecated sleep method for the broken case.
+// See: https://svn.boost.org/trac/boost/ticket/7238
+#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
+#elif defined(HAVE_WORKING_BOOST_SLEEP)
+ boost::this_thread::sleep(boost::posix_time::milliseconds(n));
+#else
+//should never get here
+#error missing boost sleep implementation
+#endif
+}
+
+std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
+{
+ // std::locale takes ownership of the pointer
+ std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
+ std::stringstream ss;
+ ss.imbue(loc);
+ ss << boost::posix_time::from_time_t(nTime);
+ return ss.str();
+}
diff --git a/src/utiltime.h b/src/utiltime.h
new file mode 100644
index 0000000000..500ae4dab9
--- /dev/null
+++ b/src/utiltime.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTILTIME_H
+#define BITCOIN_UTILTIME_H
+
+#include <stdint.h>
+#include <string>
+
+int64_t GetTime();
+int64_t GetTimeMillis();
+int64_t GetTimeMicros();
+void SetMockTime(int64_t nMockTimeIn);
+void MilliSleep(int64_t n);
+
+std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime);
+
+#endif
diff --git a/src/version.cpp b/src/version.cpp
index d86caa3ac2..8311041ed2 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -4,7 +4,10 @@
#include "version.h"
+#include "tinyformat.h"
+
#include <string>
+#include <boost/algorithm/string/join.hpp>
// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
@@ -69,3 +72,28 @@ const std::string CLIENT_NAME("Satoshi");
const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
+
+static std::string FormatVersion(int nVersion)
+{
+ if (nVersion%100 == 0)
+ return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
+ else
+ return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
+}
+
+std::string FormatFullVersion()
+{
+ return CLIENT_BUILD;
+}
+
+// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
+std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
+{
+ std::ostringstream ss;
+ ss << "/";
+ ss << name << ":" << FormatVersion(nClientVersion);
+ if (!comments.empty())
+ ss << "(" << boost::algorithm::join(comments, "; ") << ")";
+ ss << "/";
+ return ss.str();
+}
diff --git a/src/version.h b/src/version.h
index fbb731c91d..3a6c0f3719 100644
--- a/src/version.h
+++ b/src/version.h
@@ -7,6 +7,7 @@
#include "clientversion.h"
#include <string>
+#include <vector>
//
// client versioning
@@ -48,4 +49,7 @@ static const int BIP0031_VERSION = 60000;
// "mempool" command, enhanced "getdata" behavior starts with this version
static const int MEMPOOL_GD_VERSION = 60002;
+std::string FormatFullVersion();
+std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
+
#endif
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 7c04743c0f..91f7eaa560 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -10,8 +10,11 @@
#include "coincontrol.h"
#include "net.h"
#include "timedata.h"
+#include "util.h"
+#include "utilmoneystr.h"
#include <boost/algorithm/string/replace.hpp>
+#include <boost/thread.hpp>
using namespace std;
@@ -37,6 +40,11 @@ struct CompareValueOnly
}
};
+std::string COutput::ToString() const
+{
+ return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str());
+}
+
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
{
LOCK(cs_wallet);
@@ -2168,3 +2176,20 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st
}
return false;
}
+
+CKeyPool::CKeyPool()
+{
+ nTime = GetTime();
+}
+
+CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
+{
+ nTime = GetTime();
+ vchPubKey = vchPubKeyIn;
+}
+
+CWalletKey::CWalletKey(int64_t nExpires)
+{
+ nTimeCreated = (nExpires ? GetTime() : 0);
+ nTimeExpires = nExpires;
+}
diff --git a/src/wallet.h b/src/wallet.h
index 34c699e979..bdb0264729 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -11,7 +11,6 @@
#include "keystore.h"
#include "main.h"
#include "ui_interface.h"
-#include "util.h"
#include "walletdb.h"
#include <algorithm>
@@ -61,16 +60,8 @@ public:
int64_t nTime;
CPubKey vchPubKey;
- CKeyPool()
- {
- nTime = GetTime();
- }
-
- CKeyPool(const CPubKey& vchPubKeyIn)
- {
- nTime = GetTime();
- vchPubKey = vchPubKeyIn;
- }
+ CKeyPool();
+ CKeyPool(const CPubKey& vchPubKeyIn);
IMPLEMENT_SERIALIZE
(
@@ -820,10 +811,7 @@ public:
tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
}
- std::string ToString() const
- {
- return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str());
- }
+ std::string ToString() const;
};
@@ -840,11 +828,7 @@ public:
//// todo: add something to note what created it (user, getnewaddress, change)
//// maybe should have a map<string, string> property map
- CWalletKey(int64_t nExpires=0)
- {
- nTimeCreated = (nExpires ? GetTime() : 0);
- nTimeExpires = nExpires;
- }
+ CWalletKey(int64_t nExpires=0);
IMPLEMENT_SERIALIZE
(
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index a95baf83d0..2fa6071658 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -9,10 +9,13 @@
#include "protocol.h"
#include "serialize.h"
#include "sync.h"
+#include "utiltime.h"
+#include "util.h"
#include "wallet.h"
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
using namespace std;
using namespace boost;