aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPieter Wuille <[email protected]>2014-08-26 16:52:58 +0200
committerPieter Wuille <[email protected]>2014-08-26 16:57:05 +0200
commit3da58b216b5726461b45685aa99cab9deb78c6fd (patch)
tree6c5b2a258ba5e80e30b23fea85fc3d23934bbcc9 /src
parentMerge pull request #4763 (diff)
parentSplit up util.cpp/h (diff)
downloaddiscoin-3da58b216b5726461b45685aa99cab9deb78c6fd.tar.xz
discoin-3da58b216b5726461b45685aa99cab9deb78c6fd.zip
Merge pull request #4748
ad49c25 Split up util.cpp/h (Wladimir J. van der Laan) f841aa2 Move `COIN` and `CENT` to core.h (Wladimir J. van der Laan) 6e5fd00 Move `*Version()` functions to version.h/cpp (Wladimir J. van der Laan) b4aa769 Move `S_I*` constants and `MSG_NOSIGNAL` to compat.h (Wladimir J. van der Laan) af8297c Move functions in wallet.h to implementation file (Wladimir J. van der Laan) 651480c move functions in main and net to implementation files (Wladimir J. van der Laan) 610a8c0 Move SetThreadPriority implementation to util.cpp instead of the header (Wladimir J. van der Laan) f780e65 Remove unused function `ByteReverse` from util.h (Wladimir J. van der Laan) 121d6ad Remove unused `alignup` function from util.h (Wladimir J. van der Laan) d1e26d4 Move CMedianFilter to timedata.cpp (Wladimir J. van der Laan)
Diffstat (limited to 'src')
-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 6c67dee7d..655bfc88c 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 cc407f679..b4360831b 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 2cd684cc4..3271ecfbf 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 0609adcab..871aaf93d 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 6cd2768d7..75f0fb69f 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 880955481..5be870897 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 52c781713..4fc28a36e 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 9552f7025..e3ceac97a 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 37dd69f7b..b395b5c09 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 122e06d97..8aa2bb051 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 eb40f3cc4..8c139843a 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 708e6386a..e972413c4 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 2a4c88d56..c6322eadc 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 1c9b3f861..6567c77e9 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 f93b78d8e..e5357cbfd 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 06acff1c3..8696edcf6 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 cae9b70da..e2adba851 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 1a7b3c00b..bfad32b2c 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 e9207da33..d5821d446 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 32c861b0d..8b00fd405 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 c0d0a7ca2..b091cbec3 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 a43e7cb75..12277a8ad 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 bfca5e8d1..d0a5ff13c 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 4c21eb559..9c9ff5b3a 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 fd1d446f9..c775a7f8d 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 a9f1566d6..f6a4b599d 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 4f6e3169f..8258e719a 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 5fb0da145..7df9d1bc2 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 0d20d205a..22c942acc 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 e511fe422..58cab1404 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 ff2361482..e68ddee04 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 edab427cb..6e508abcd 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 643208b3b..808b9bbd2 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 524627e2d..c9133bd3d 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 d6d6684f4..28c50a135 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 1e2cc94ef..462e3f230 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 5e17555e7..4ecf6e253 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 e3066a51a..4af87cf8e 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 2752a0b21..69888da3d 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 87473585e..68617abbd 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 d4a23d9aa..f2bf3326a 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 10352240f..fdea12846 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 a17278b80..a3eec270e 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 4568c8769..b8e290f07 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 443b5853b..68fad8d03 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 000000000..aa4fa0d50
--- /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 068b9f29c..e077c9de3 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 4576786b9..40cdb33f7 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 0e7bdc2c1..d0c84b318 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 929cb66e4..73d49a1fe 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 2349514de..d4c600755 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 f75e2212d..8af1f1c91 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 08c05594f..feda0ca5a 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 ae2145a3a..5a4e187f9 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 1fb42a7b7..30f7c15c8 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 000000000..1bd48d8d4
--- /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 000000000..f0c61aa13
--- /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 000000000..ef1355510
--- /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 000000000..0b8c1a178
--- /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 000000000..78f0342cb
--- /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 000000000..500ae4dab
--- /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 d86caa3ac..8311041ed 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 fbb731c91..3a6c0f371 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 7c04743c0..91f7eaa56 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 34c699e97..bdb026472 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 a95baf83d..2fa607165 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;