aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/base58.cpp4
-rw-r--r--src/checkpoints.cpp7
-rw-r--r--src/checkpoints.h7
-rw-r--r--src/init.h2
-rw-r--r--src/key.cpp3
-rw-r--r--src/main.cpp121
-rw-r--r--src/main.h13
-rw-r--r--src/net.h3
-rw-r--r--src/qt/utilitydialog.cpp1
-rw-r--r--src/rpcblockchain.cpp2
-rw-r--r--src/rpcmining.cpp2
-rw-r--r--src/rpcnet.cpp1
-rw-r--r--src/rpcprotocol.cpp42
-rw-r--r--src/rpcprotocol.h2
-rw-r--r--src/rpcserver.cpp18
-rw-r--r--src/rpcserver.h1
-rw-r--r--src/script.cpp5
-rw-r--r--src/test/skiplist_tests.cpp45
-rw-r--r--src/uint256.cpp292
-rw-r--r--src/uint256.h262
-rw-r--r--src/util.cpp8
-rw-r--r--src/util.h1
24 files changed, 540 insertions, 304 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3643e60201..9c7b294d35 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -192,6 +192,7 @@ libbitcoin_util_a_SOURCES = \
chainparamsbase.cpp \
rpcprotocol.cpp \
sync.cpp \
+ uint256.cpp \
util.cpp \
version.cpp \
compat/glibc_sanity.cpp \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 4dab1773f4..8685452c7b 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -47,6 +47,7 @@ BITCOIN_TESTS =\
test/script_tests.cpp \
test/serialize_tests.cpp \
test/sigopcount_tests.cpp \
+ test/skiplist_tests.cpp \
test/test_bitcoin.cpp \
test/transaction_tests.cpp \
test/uint256_tests.cpp \
diff --git a/src/base58.cpp b/src/base58.cpp
index 1bd64684e5..c9e91beef1 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -186,6 +186,7 @@ int CBase58Data::CompareTo(const CBase58Data& b58) const {
}
namespace {
+
class CBitcoinAddressVisitor : public boost::static_visitor<bool> {
private:
CBitcoinAddress *addr;
@@ -196,7 +197,8 @@ namespace {
bool operator()(const CScriptID &id) const { return addr->Set(id); }
bool operator()(const CNoDestination &no) const { return false; }
};
-};
+
+} // anon namespace
bool CBitcoinAddress::Set(const CKeyID &id) {
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 75ac418916..80479b47fb 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -12,8 +12,8 @@
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>
-namespace Checkpoints
-{
+namespace Checkpoints {
+
typedef std::map<int, uint256> MapCheckpoints;
// How many times we expect transactions after the last checkpoint to
@@ -161,4 +161,5 @@ namespace Checkpoints
}
return NULL;
}
-}
+
+} // namespace Checkpoints
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 1b4aacee20..2cf8d41b9d 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -13,8 +13,8 @@ class uint256;
/** Block-chain checkpoints are compiled-in sanity checks.
* They are updated every release or three.
*/
-namespace Checkpoints
-{
+namespace Checkpoints {
+
// Returns true if block passes checkpoint checks
bool CheckBlock(int nHeight, const uint256& hash);
@@ -27,6 +27,7 @@ namespace Checkpoints
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true);
extern bool fEnabled;
-}
+
+} //namespace Checkpoints
#endif
diff --git a/src/init.h b/src/init.h
index 52daa47616..626525c9ad 100644
--- a/src/init.h
+++ b/src/init.h
@@ -12,7 +12,7 @@ class CWallet;
namespace boost {
class thread_group;
-};
+} // namespace boost
extern CWallet* pwalletMain;
diff --git a/src/key.cpp b/src/key.cpp
index 96b1ac439c..784085da34 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -377,8 +377,7 @@ const unsigned char vchMaxModHalfOrder[32] = {
const unsigned char vchZero[0] = {};
-
-}; // end of anonymous namespace
+} // anon namespace
bool CKey::Check(const unsigned char *vch) {
return CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
diff --git a/src/main.cpp b/src/main.cpp
index df810f575f..04d9523e26 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -73,6 +73,7 @@ const string strMessageMagic = "Bitcoin Signed Message:\n";
// Internal stuff
namespace {
+
struct CBlockIndexWorkComparator
{
bool operator()(CBlockIndex *pa, CBlockIndex *pb) {
@@ -121,7 +122,8 @@ namespace {
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
map<uint256, pair<NodeId, list<uint256>::iterator> > mapBlocksToDownload;
-}
+
+} // anon namespace
// Forward reference functions defined here:
static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000;
@@ -135,6 +137,7 @@ static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doub
// These functions dispatch to one or all registered wallets
namespace {
+
struct CMainSignals {
// Notifies listeners of updated transaction data (transaction, and optionally the block it is found in.
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
@@ -155,7 +158,8 @@ struct CMainSignals {
// then the double-spend simply fails when we try to lookup the inputs in the current UTXO set.
boost::signals2::signal<void (const COutPoint&, const CTransaction&, bool)> DetectedDoubleSpend;
} g_signals;
-}
+
+} // anon namespace
void RegisterInternalSignals() {
static CBloomFilter doubleSpendFilter;
@@ -223,6 +227,10 @@ struct CNodeState {
std::string name;
// List of asynchronously-determined block rejections to notify this peer about.
std::vector<CBlockReject> rejects;
+ // The best known block we know this peer has announced.
+ CBlockIndex *pindexBestKnownBlock;
+ // The hash of the last unknown block this peer has announced.
+ uint256 hashLastUnknownBlock;
list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight;
list<uint256> vBlocksToDownload;
@@ -233,6 +241,8 @@ struct CNodeState {
CNodeState() {
nMisbehavior = 0;
fShouldBan = false;
+ pindexBestKnownBlock = NULL;
+ hashLastUnknownBlock = uint256(0);
nBlocksToDownload = 0;
nBlocksInFlight = 0;
nLastBlockReceive = 0;
@@ -294,7 +304,6 @@ void MarkBlockAsReceived(const uint256 &hash, NodeId nodeFrom = -1) {
state->nLastBlockReceive = GetTimeMicros();
mapBlocksInFlight.erase(itInFlight);
}
-
}
// Requires cs_main.
@@ -330,14 +339,48 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256 &hash) {
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
}
+/** Check whether the last unknown block a peer advertized is not yet known. */
+void ProcessBlockAvailability(NodeId nodeid) {
+ CNodeState *state = State(nodeid);
+ assert(state != NULL);
+
+ if (state->hashLastUnknownBlock != 0) {
+ map<uint256, CBlockIndex*>::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock);
+ if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) {
+ if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
+ state->pindexBestKnownBlock = itOld->second;
+ state->hashLastUnknownBlock = uint256(0);
+ }
+ }
+}
+
+/** Update tracking information about which blocks a peer is assumed to have. */
+void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
+ CNodeState *state = State(nodeid);
+ assert(state != NULL);
+
+ ProcessBlockAvailability(nodeid);
+
+ map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hash);
+ if (it != mapBlockIndex.end() && it->second->nChainWork > 0) {
+ // An actually better block was announced.
+ if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
+ state->pindexBestKnownBlock = it->second;
+ } else {
+ // An unknown block was announced; just assume that the latest one is the best one.
+ state->hashLastUnknownBlock = hash;
+ }
}
+} // anon namespace
+
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
LOCK(cs_main);
CNodeState *state = State(nodeid);
if (state == NULL)
return false;
stats.nMisbehavior = state->nMisbehavior;
+ stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
return true;
}
@@ -391,8 +434,11 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
break;
// Exponentially larger steps back, plus the genesis block.
int nHeight = std::max(pindex->nHeight - nStep, 0);
+ // Jump back quickly to the same height as the chain.
+ if (pindex->nHeight > nHeight)
+ pindex = pindex->GetAncestor(nHeight);
// In case pindex is not in this chain, iterate pindex->pprev to find blocks.
- while (pindex->nHeight > nHeight && !Contains(pindex))
+ while (!Contains(pindex))
pindex = pindex->pprev;
// If pindex is in this chain, use direct height-based access.
if (pindex->nHeight > nHeight)
@@ -419,6 +465,8 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
}
CBlockIndex *CChain::FindFork(CBlockIndex *pindex) const {
+ if (pindex->nHeight > Height())
+ pindex = pindex->GetAncestor(Height());
while (pindex && !Contains(pindex))
pindex = pindex->pprev;
return pindex;
@@ -508,7 +556,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
// Treat non-final transactions as non-standard to prevent a specific type
// of double-spend attack, as well as DoS attacks. (if the transaction
// can't be mined, the attacker isn't expending resources broadcasting it)
- // Basically we don't want to propagate transactions that can't included in
+ // Basically we don't want to propagate transactions that can't be included in
// the next block.
//
// However, IsFinalTx() is confusing... Without arguments, it uses
@@ -541,7 +589,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
{
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
// keys. (remember the 520 byte limit on redeemScript size) That works
- // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624
+ // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
// bytes of scriptSig, which we round off to 1650 bytes for some minor
// future-proofing. That's also enough to spend a 20-of-20
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
@@ -2178,6 +2226,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block)
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
+ pindexNew->BuildSkip();
}
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork();
pindexNew->RaiseValidity(BLOCK_VALID_TREE);
@@ -2535,6 +2584,55 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
return (nFound >= nRequired);
}
+/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
+int static inline InvertLowestOne(int n) { return n & (n - 1); }
+
+/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
+int static inline GetSkipHeight(int height) {
+ if (height < 2)
+ return 0;
+
+ // Determine which height to jump back to. Any number strictly lower than height is acceptable,
+ // but the following expression seems to perform well in simulations (max 110 steps to go back
+ // up to 2**18 blocks).
+ return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
+}
+
+CBlockIndex* CBlockIndex::GetAncestor(int height)
+{
+ if (height > nHeight || height < 0)
+ return NULL;
+
+ CBlockIndex* pindexWalk = this;
+ int heightWalk = nHeight;
+ while (heightWalk > height) {
+ int heightSkip = GetSkipHeight(heightWalk);
+ int heightSkipPrev = GetSkipHeight(heightWalk - 1);
+ if (heightSkip == height ||
+ (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
+ heightSkipPrev >= height))) {
+ // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
+ pindexWalk = pindexWalk->pskip;
+ heightWalk = heightSkip;
+ } else {
+ pindexWalk = pindexWalk->pprev;
+ heightWalk--;
+ }
+ }
+ return pindexWalk;
+}
+
+const CBlockIndex* CBlockIndex::GetAncestor(int height) const
+{
+ return const_cast<CBlockIndex*>(this)->GetAncestor(height);
+}
+
+void CBlockIndex::BuildSkip()
+{
+ if (pprev)
+ pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
+}
+
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
{
AssertLockHeld(cs_main);
@@ -2885,6 +2983,8 @@ bool static LoadBlockIndexDB()
setBlockIndexValid.insert(pindex);
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
pindexBestInvalid = pindex;
+ if (pindex->pprev)
+ pindex->BuildSkip();
}
// Load block file info
@@ -3680,6 +3780,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(inv.hash));
}
+ if (inv.type == MSG_BLOCK)
+ UpdateBlockAvailability(pfrom->GetId(), inv.hash);
+
// Track requests for our stuff
g_signals.Inventory(inv.hash);
}
@@ -3722,7 +3825,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pindex)
pindex = chainActive.Next(pindex);
int nLimit = 500;
- LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), nLimit);
+ LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop==uint256(0) ? "end" : hashStop.ToString(), nLimit);
for (; pindex; pindex = chainActive.Next(pindex))
{
if (pindex->GetBlockHash() == hashStop)
@@ -4111,6 +4214,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else
{
// Ignore unknown commands for extensibility
+ LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
}
@@ -4425,6 +4529,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->fDisconnect = true;
}
+ // Update knowledge of peer's block availability.
+ ProcessBlockAvailability(pto->GetId());
+
//
// Message: getdata (blocks)
//
diff --git a/src/main.h b/src/main.h
index c7f3dc4388..19f4469008 100644
--- a/src/main.h
+++ b/src/main.h
@@ -188,6 +188,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
struct CNodeStateStats {
int nMisbehavior;
+ int nSyncHeight;
};
struct CDiskBlockPos
@@ -679,6 +680,9 @@ public:
// pointer to the index of the predecessor of this block
CBlockIndex* pprev;
+ // pointer to the index of some further predecessor of this block
+ CBlockIndex* pskip;
+
// height of the entry in the chain. The genesis block has height 0
int nHeight;
@@ -718,6 +722,7 @@ public:
{
phashBlock = NULL;
pprev = NULL;
+ pskip = NULL;
nHeight = 0;
nFile = 0;
nDataPos = 0;
@@ -739,6 +744,7 @@ public:
{
phashBlock = NULL;
pprev = NULL;
+ pskip = NULL;
nHeight = 0;
nFile = 0;
nDataPos = 0;
@@ -871,9 +877,14 @@ public:
}
return false;
}
-};
+ // Build the skiplist pointer for this entry.
+ void BuildSkip();
+ // Efficiently find an ancestor of this block.
+ CBlockIndex* GetAncestor(int height);
+ const CBlockIndex* GetAncestor(int height) const;
+};
/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex
diff --git a/src/net.h b/src/net.h
index 41dc618571..2ee798d468 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,14 +28,13 @@
#include <boost/signals2/signal.hpp>
#include <openssl/rand.h>
-
class CAddrMan;
class CBlockIndex;
class CNode;
namespace boost {
class thread_group;
-}
+} // namespace boost
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
static const int PING_INTERVAL = 2 * 60;
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index eb647d0170..5fb0da145d 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -117,6 +117,7 @@ void ShutdownWindow::showShutdownWindow(BitcoinGUI *window)
tr("Bitcoin Core is shutting down...") + "<br /><br />" +
tr("Do not shut down the computer until this window disappears.")));
shutdownWindow->setLayout(layout);
+ shutdownWindow->setWindowTitle(window->windowTitle());
// Center shutdown window at where main window was
const QPoint global = window->mapToGlobal(window->rect().center());
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 580c6bd5ba..a67f266a13 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -66,7 +66,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
result.push_back(Pair("tx", txs));
result.push_back(Pair("time", block.GetBlockTime()));
result.push_back(Pair("nonce", (uint64_t)block.nNonce));
- result.push_back(Pair("bits", HexBits(block.nBits)));
+ result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 98caf704ee..db60ef3592 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -443,7 +443,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
result.push_back(Pair("curtime", (int64_t)pblock->nTime));
- result.push_back(Pair("bits", HexBits(pblock->nBits)));
+ result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
return result;
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index a54872ccc4..2d7abb2d58 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -134,6 +134,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("startingheight", stats.nStartingHeight));
if (fStateStats) {
obj.push_back(Pair("banscore", statestats.nMisbehavior));
+ obj.push_back(Pair("syncheight", statestats.nSyncHeight));
}
obj.push_back(Pair("syncnode", stats.fSyncNode));
diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp
index 2cb4a35c4b..dd8692e802 100644
--- a/src/rpcprotocol.cpp
+++ b/src/rpcprotocol.cpp
@@ -54,8 +54,19 @@ static string rfc1123Time()
return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime());
}
-string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
- bool headersOnly, const char *contentType)
+static const char *httpStatusDescription(int nStatus)
+{
+ switch (nStatus) {
+ case HTTP_OK: return "OK";
+ case HTTP_BAD_REQUEST: return "Bad Request";
+ case HTTP_FORBIDDEN: return "Forbidden";
+ case HTTP_NOT_FOUND: return "Not Found";
+ case HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error";
+ default: return "";
+ }
+}
+
+string HTTPError(int nStatus, bool keepalive, bool headersOnly)
{
if (nStatus == HTTP_UNAUTHORIZED)
return strprintf("HTTP/1.0 401 Authorization Required\r\n"
@@ -75,20 +86,13 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
"<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
"</HTML>\r\n", rfc1123Time(), FormatFullVersion());
- const char *cStatus;
- if (nStatus == HTTP_OK) cStatus = "OK";
- else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request";
- else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden";
- else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found";
- else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error";
- else cStatus = "";
-
- bool useInternalContent = false;
- if (nStatus != HTTP_OK) {
- contentType = "text/plain";
- useInternalContent = true;
- }
+ return HTTPReply(nStatus, httpStatusDescription(nStatus), keepalive,
+ headersOnly, "text/plain");
+}
+string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
+ bool headersOnly, const char *contentType)
+{
return strprintf(
"HTTP/1.1 %d %s\r\n"
"Date: %s\r\n"
@@ -99,14 +103,14 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive,
"\r\n"
"%s",
nStatus,
- cStatus,
+ httpStatusDescription(nStatus),
rfc1123Time(),
keepalive ? "keep-alive" : "close",
- strMsg.size(),
+ (headersOnly ? 0 : strMsg.size()),
contentType,
FormatFullVersion(),
- (headersOnly ? "" :
- (useInternalContent ? cStatus : strMsg.c_str())));
+ (headersOnly ? "" : strMsg.c_str())
+ );
}
bool ReadHTTPRequestLine(std::basic_istream<char>& stream, int &proto,
diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h
index f1317e9c28..5627077bfb 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -141,6 +141,8 @@ private:
};
std::string HTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
+std::string HTTPError(int nStatus, bool keepalive,
+ bool headerOnly = false);
std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive,
bool headerOnly = false,
const char *contentType = "application/json");
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 54043458d5..f47b3385da 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -97,16 +97,6 @@ Value ValueFromAmount(int64_t amount)
return (double)amount / (double)COIN;
}
-std::string HexBits(unsigned int nBits)
-{
- union {
- int32_t nBits;
- char cBits[4];
- } uBits;
- uBits.nBits = htonl((int32_t)nBits);
- return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
-}
-
uint256 ParseHashV(const Value& v, string strName)
{
string strHex;
@@ -491,7 +481,7 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
{
// Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
if (!fUseSSL)
- conn->stream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush;
+ conn->stream() << HTTPError(HTTP_FORBIDDEN, false) << std::flush;
conn->close();
}
else {
@@ -817,7 +807,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
// Check authorization
if (mapHeaders.count("authorization") == 0)
{
- conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush;
+ conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush;
return false;
}
@@ -830,7 +820,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
if (mapArgs["-rpcpassword"].size() < 20)
MilliSleep(250);
- conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush;
+ conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush;
return false;
}
@@ -898,7 +888,7 @@ void ServiceConnection(AcceptedConnection *conn)
if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun))
break;
} else {
- conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush;
+ conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush;
break;
}
}
diff --git a/src/rpcserver.h b/src/rpcserver.h
index fcd293663f..01e77163c4 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -116,7 +116,6 @@ extern int64_t nWalletUnlockTime;
extern int64_t AmountFromValue(const json_spirit::Value& value);
extern json_spirit::Value ValueFromAmount(int64_t amount);
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
-extern std::string HexBits(unsigned int nBits);
extern std::string HelpRequiringPassphrase();
extern std::string HelpExampleCli(std::string methodname, std::string args);
extern std::string HelpExampleRpc(std::string methodname, std::string args);
diff --git a/src/script.cpp b/src/script.cpp
index bc4705abe7..e1b6985408 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -974,6 +974,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
namespace {
+
/** Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
@@ -1066,7 +1067,8 @@ public:
::Serialize(s, txTo.nLockTime, nType, nVersion);
}
};
-}
+
+} // anon namespace
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
@@ -1092,7 +1094,6 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
-
// Valid signature cache, to avoid doing expensive ECDSA signature checking
// twice for every transaction (once when accepted into memory pool, and
// again when accepted into the block chain)
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
new file mode 100644
index 0000000000..ea301685c9
--- /dev/null
+++ b/src/test/skiplist_tests.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) 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 <boost/test/unit_test.hpp>
+#include <vector>
+#include "main.h"
+#include "util.h"
+
+
+#define SKIPLIST_LENGTH 300000
+
+BOOST_AUTO_TEST_SUITE(skiplist_tests)
+
+BOOST_AUTO_TEST_CASE(skiplist_test)
+{
+ std::vector<CBlockIndex> vIndex(SKIPLIST_LENGTH);
+
+ for (int i=0; i<SKIPLIST_LENGTH; i++) {
+ vIndex[i].nHeight = i;
+ vIndex[i].pprev = (i == 0) ? NULL : &vIndex[i - 1];
+ vIndex[i].BuildSkip();
+ }
+
+ for (int i=0; i<SKIPLIST_LENGTH; i++) {
+ if (i > 0) {
+ BOOST_CHECK(vIndex[i].pskip == &vIndex[vIndex[i].pskip->nHeight]);
+ BOOST_CHECK(vIndex[i].pskip->nHeight < i);
+ } else {
+ BOOST_CHECK(vIndex[i].pskip == NULL);
+ }
+ }
+
+ for (int i=0; i < 1000; i++) {
+ int from = insecure_rand() % (SKIPLIST_LENGTH - 1);
+ int to = insecure_rand() % (from + 1);
+
+ BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
+ BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
+ BOOST_CHECK(vIndex[from].GetAncestor(0) == &vIndex[0]);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/src/uint256.cpp b/src/uint256.cpp
new file mode 100644
index 0000000000..3392f1e9bc
--- /dev/null
+++ b/src/uint256.cpp
@@ -0,0 +1,292 @@
+// 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 "uint256.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <string.h>
+
+template<unsigned int BITS>
+base_uint<BITS>::base_uint(const std::string& str)
+{
+ SetHex(str);
+}
+
+template<unsigned int BITS>
+base_uint<BITS>::base_uint(const std::vector<unsigned char>& vch)
+{
+ if (vch.size() != sizeof(pn))
+ throw uint_error("Converting vector of wrong size to base_uint");
+ memcpy(pn, &vch[0], sizeof(pn));
+}
+
+template<unsigned int BITS>
+base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift)
+{
+ base_uint<BITS> a(*this);
+ for (int i = 0; i < WIDTH; i++)
+ pn[i] = 0;
+ int k = shift / 32;
+ shift = shift % 32;
+ for (int i = 0; i < WIDTH; i++) {
+ if (i+k+1 < WIDTH && shift != 0)
+ pn[i+k+1] |= (a.pn[i] >> (32-shift));
+ if (i+k < WIDTH)
+ pn[i+k] |= (a.pn[i] << shift);
+ }
+ return *this;
+}
+
+template<unsigned int BITS>
+base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift)
+{
+ base_uint<BITS> a(*this);
+ for (int i = 0; i < WIDTH; i++)
+ pn[i] = 0;
+ int k = shift / 32;
+ shift = shift % 32;
+ for (int i = 0; i < WIDTH; i++) {
+ if (i-k-1 >= 0 && shift != 0)
+ pn[i-k-1] |= (a.pn[i] << (32-shift));
+ if (i-k >= 0)
+ pn[i-k] |= (a.pn[i] >> shift);
+ }
+ return *this;
+}
+
+template<unsigned int BITS>
+base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32)
+{
+ uint64_t carry = 0;
+ for (int i = 0; i < WIDTH; i++) {
+ uint64_t n = carry + (uint64_t)b32 * pn[i];
+ pn[i] = n & 0xffffffff;
+ carry = n >> 32;
+ }
+ return *this;
+}
+
+template<unsigned int BITS>
+base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b)
+{
+ base_uint<BITS> a = *this;
+ *this = 0;
+ for (int j = 0; j < WIDTH; j++) {
+ uint64_t carry = 0;
+ for (int i = 0; i + j < WIDTH; i++) {
+ uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i];
+ pn[i + j] = n & 0xffffffff;
+ carry = n >> 32;
+ }
+ }
+ return *this;
+}
+
+template<unsigned int BITS>
+base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b)
+{
+ base_uint<BITS> div = b; // make a copy, so we can shift.
+ base_uint<BITS> num = *this; // make a copy, so we can subtract.
+ *this = 0; // the quotient.
+ int num_bits = num.bits();
+ int div_bits = div.bits();
+ if (div_bits == 0)
+ throw uint_error("Division by zero");
+ if (div_bits > num_bits) // the result is certainly 0.
+ return *this;
+ int shift = num_bits - div_bits;
+ div <<= shift; // shift so that div and nun align.
+ while (shift >= 0) {
+ if (num >= div) {
+ num -= div;
+ pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
+ }
+ div >>= 1; // shift back.
+ shift--;
+ }
+ // num now contains the remainder of the division.
+ return *this;
+}
+
+template<unsigned int BITS>
+int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const {
+ for (int i = WIDTH-1; i >= 0; i--) {
+ if (pn[i] < b.pn[i])
+ return -1;
+ if (pn[i] > b.pn[i])
+ return 1;
+ }
+ return 0;
+}
+
+template<unsigned int BITS>
+bool base_uint<BITS>::EqualTo(uint64_t b) const {
+ for (int i = WIDTH-1; i >= 2; i--) {
+ if (pn[i])
+ return false;
+ }
+ if (pn[1] != (b >> 32))
+ return false;
+ if (pn[0] != (b & 0xfffffffful))
+ return false;
+ return true;
+}
+
+template<unsigned int BITS>
+double base_uint<BITS>::getdouble() const
+{
+ double ret = 0.0;
+ double fact = 1.0;
+ for (int i = 0; i < WIDTH; i++) {
+ ret += fact * pn[i];
+ fact *= 4294967296.0;
+ }
+ return ret;
+}
+
+template<unsigned int BITS>
+std::string base_uint<BITS>::GetHex() const
+{
+ char psz[sizeof(pn)*2 + 1];
+ for (unsigned int i = 0; i < sizeof(pn); i++)
+ sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
+ return std::string(psz, psz + sizeof(pn)*2);
+}
+
+template<unsigned int BITS>
+void base_uint<BITS>::SetHex(const char* psz)
+{
+ memset(pn,0,sizeof(pn));
+
+ // skip leading spaces
+ while (isspace(*psz))
+ psz++;
+
+ // skip 0x
+ if (psz[0] == '0' && tolower(psz[1]) == 'x')
+ psz += 2;
+
+ // hex string to uint
+ const char* pbegin = psz;
+ while (::HexDigit(*psz) != -1)
+ psz++;
+ psz--;
+ unsigned char* p1 = (unsigned char*)pn;
+ unsigned char* pend = p1 + WIDTH * 4;
+ while (psz >= pbegin && p1 < pend) {
+ *p1 = ::HexDigit(*psz--);
+ if (psz >= pbegin) {
+ *p1 |= ((unsigned char)::HexDigit(*psz--) << 4);
+ p1++;
+ }
+ }
+}
+
+template<unsigned int BITS>
+void base_uint<BITS>::SetHex(const std::string& str)
+{
+ SetHex(str.c_str());
+}
+
+template<unsigned int BITS>
+std::string base_uint<BITS>::ToString() const
+{
+ return (GetHex());
+}
+
+template<unsigned int BITS>
+unsigned int base_uint<BITS>::bits() const
+{
+ for (int pos = WIDTH-1; pos >= 0; pos--) {
+ if (pn[pos]) {
+ for (int bits = 31; bits > 0; bits--) {
+ if (pn[pos] & 1<<bits)
+ return 32*pos + bits + 1;
+ }
+ return 32*pos + 1;
+ }
+ }
+ return 0;
+}
+
+// Explicit instantiations for base_uint<160>
+template base_uint<160>::base_uint(const std::string&);
+template base_uint<160>::base_uint(const std::vector<unsigned char>&);
+template base_uint<160>& base_uint<160>::operator<<=(unsigned int);
+template base_uint<160>& base_uint<160>::operator>>=(unsigned int);
+template base_uint<160>& base_uint<160>::operator*=(uint32_t b32);
+template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b);
+template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b);
+template int base_uint<160>::CompareTo(const base_uint<160>&) const;
+template bool base_uint<160>::EqualTo(uint64_t) const;
+template double base_uint<160>::getdouble() const;
+template std::string base_uint<160>::GetHex() const;
+template std::string base_uint<160>::ToString() const;
+template void base_uint<160>::SetHex(const char*);
+template void base_uint<160>::SetHex(const std::string&);
+template unsigned int base_uint<160>::bits() const;
+
+// Explicit instantiations for base_uint<256>
+template base_uint<256>::base_uint(const std::string&);
+template base_uint<256>::base_uint(const std::vector<unsigned char>&);
+template base_uint<256>& base_uint<256>::operator<<=(unsigned int);
+template base_uint<256>& base_uint<256>::operator>>=(unsigned int);
+template base_uint<256>& base_uint<256>::operator*=(uint32_t b32);
+template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b);
+template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b);
+template int base_uint<256>::CompareTo(const base_uint<256>&) const;
+template bool base_uint<256>::EqualTo(uint64_t) const;
+template double base_uint<256>::getdouble() const;
+template std::string base_uint<256>::GetHex() const;
+template std::string base_uint<256>::ToString() const;
+template void base_uint<256>::SetHex(const char*);
+template void base_uint<256>::SetHex(const std::string&);
+template unsigned int base_uint<256>::bits() const;
+
+// This implementation directly uses shifts instead of going
+// through an intermediate MPI representation.
+uint256& uint256::SetCompact(uint32_t nCompact, bool *pfNegative, bool *pfOverflow)
+{
+ int nSize = nCompact >> 24;
+ uint32_t nWord = nCompact & 0x007fffff;
+ if (nSize <= 3) {
+ nWord >>= 8*(3-nSize);
+ *this = nWord;
+ } else {
+ *this = nWord;
+ *this <<= 8*(nSize-3);
+ }
+ if (pfNegative)
+ *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
+ if (pfOverflow)
+ *pfOverflow = nWord != 0 && ((nSize > 34) ||
+ (nWord > 0xff && nSize > 33) ||
+ (nWord > 0xffff && nSize > 32));
+ return *this;
+}
+
+uint32_t uint256::GetCompact(bool fNegative) const
+{
+ int nSize = (bits() + 7) / 8;
+ uint32_t nCompact = 0;
+ if (nSize <= 3) {
+ nCompact = GetLow64() << 8*(3-nSize);
+ } else {
+ uint256 bn = *this >> 8*(nSize-3);
+ nCompact = bn.GetLow64();
+ }
+ // The 0x00800000 bit denotes the sign.
+ // Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
+ if (nCompact & 0x00800000) {
+ nCompact >>= 8;
+ nSize++;
+ }
+ assert((nCompact & ~0x007fffff) == 0);
+ assert(nSize < 256);
+ nCompact |= nSize << 24;
+ nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
+ return nCompact;
+}
diff --git a/src/uint256.h b/src/uint256.h
index 1acedd14bf..82db7758c9 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -9,18 +9,9 @@
#include <assert.h>
#include <stdexcept>
#include <stdint.h>
-#include <stdio.h>
#include <string>
-#include <string.h>
#include <vector>
-extern const signed char p_util_hexdigit[256]; // defined in util.cpp
-
-inline signed char HexDigit(char c)
-{
- return p_util_hexdigit[(unsigned char)c];
-}
-
class uint_error : public std::runtime_error {
public:
explicit uint_error(const std::string& str) : std::runtime_error(str) {}
@@ -62,17 +53,8 @@ public:
pn[i] = 0;
}
- explicit base_uint(const std::string& str)
- {
- SetHex(str);
- }
-
- explicit base_uint(const std::vector<unsigned char>& vch)
- {
- if (vch.size() != sizeof(pn))
- throw uint_error("Converting vector of wrong size to base_uint");
- memcpy(pn, &vch[0], sizeof(pn));
- }
+ explicit base_uint(const std::string& str);
+ explicit base_uint(const std::vector<unsigned char>& vch);
bool operator!() const
{
@@ -99,16 +81,7 @@ public:
return ret;
}
- double getdouble() const
- {
- double ret = 0.0;
- double fact = 1.0;
- for (int i = 0; i < WIDTH; i++) {
- ret += fact * pn[i];
- fact *= 4294967296.0;
- }
- return ret;
- }
+ double getdouble() const;
base_uint& operator=(uint64_t b)
{
@@ -154,39 +127,8 @@ public:
return *this;
}
- base_uint& operator<<=(unsigned int shift)
- {
- base_uint a(*this);
- for (int i = 0; i < WIDTH; i++)
- pn[i] = 0;
- int k = shift / 32;
- shift = shift % 32;
- for (int i = 0; i < WIDTH; i++)
- {
- if (i+k+1 < WIDTH && shift != 0)
- pn[i+k+1] |= (a.pn[i] >> (32-shift));
- if (i+k < WIDTH)
- pn[i+k] |= (a.pn[i] << shift);
- }
- return *this;
- }
-
- base_uint& operator>>=(unsigned int shift)
- {
- base_uint a(*this);
- for (int i = 0; i < WIDTH; i++)
- pn[i] = 0;
- int k = shift / 32;
- shift = shift % 32;
- for (int i = 0; i < WIDTH; i++)
- {
- if (i-k-1 >= 0 && shift != 0)
- pn[i-k-1] |= (a.pn[i] << (32-shift));
- if (i-k >= 0)
- pn[i-k] |= (a.pn[i] >> shift);
- }
- return *this;
- }
+ base_uint& operator<<=(unsigned int shift);
+ base_uint& operator>>=(unsigned int shift);
base_uint& operator+=(const base_uint& b)
{
@@ -222,57 +164,9 @@ public:
return *this;
}
- base_uint& operator*=(uint32_t b32)
- {
- uint64_t carry = 0;
- for (int i = 0; i < WIDTH; i++)
- {
- uint64_t n = carry + (uint64_t)b32 * pn[i];
- pn[i] = n & 0xffffffff;
- carry = n >> 32;
- }
- return *this;
- }
-
- base_uint& operator*=(const base_uint& b)
- {
- base_uint a = *this;
- *this = 0;
- for (int j = 0; j < WIDTH; j++) {
- uint64_t carry = 0;
- for (int i = 0; i + j < WIDTH; i++) {
- uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i];
- pn[i + j] = n & 0xffffffff;
- carry = n >> 32;
- }
- }
- return *this;
- }
-
- base_uint& operator/=(const base_uint& b)
- {
- base_uint div = b; // make a copy, so we can shift.
- base_uint num = *this; // make a copy, so we can subtract.
- *this = 0; // the quotient.
- int num_bits = num.bits();
- int div_bits = div.bits();
- if (div_bits == 0)
- throw uint_error("Division by zero");
- if (div_bits > num_bits) // the result is certainly 0.
- return *this;
- int shift = num_bits - div_bits;
- div <<= shift; // shift so that div and nun align.
- while (shift >= 0) {
- if (num >= div) {
- num -= div;
- pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
- }
- div >>= 1; // shift back.
- shift--;
- }
- // num now contains the remainder of the division.
- return *this;
- }
+ base_uint& operator*=(uint32_t b32);
+ base_uint& operator*=(const base_uint& b);
+ base_uint& operator/=(const base_uint& b);
base_uint& operator++()
{
@@ -308,27 +202,8 @@ public:
return ret;
}
- int CompareTo(const base_uint& b) const {
- for (int i = base_uint::WIDTH-1; i >= 0; i--) {
- if (pn[i] < b.pn[i])
- return -1;
- if (pn[i] > b.pn[i])
- return 1;
- }
- return 0;
- }
-
- bool EqualTo(uint64_t b) const {
- for (int i = base_uint::WIDTH-1; i >= 2; i--) {
- if (pn[i])
- return false;
- }
- if (pn[1] != (b >> 32))
- return false;
- if (pn[0] != (b & 0xfffffffful))
- return false;
- return true;
- }
+ int CompareTo(const base_uint& b) const;
+ bool EqualTo(uint64_t b) const;
friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
@@ -349,53 +224,10 @@ public:
friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); }
friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); }
- std::string GetHex() const
- {
- char psz[sizeof(pn)*2 + 1];
- for (unsigned int i = 0; i < sizeof(pn); i++)
- sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
- return std::string(psz, psz + sizeof(pn)*2);
- }
-
- void SetHex(const char* psz)
- {
- memset(pn,0,sizeof(pn));
-
- // skip leading spaces
- while (isspace(*psz))
- psz++;
-
- // skip 0x
- if (psz[0] == '0' && tolower(psz[1]) == 'x')
- psz += 2;
-
- // hex string to uint
- const char* pbegin = psz;
- while (::HexDigit(*psz) != -1)
- psz++;
- psz--;
- unsigned char* p1 = (unsigned char*)pn;
- unsigned char* pend = p1 + WIDTH * 4;
- while (psz >= pbegin && p1 < pend)
- {
- *p1 = ::HexDigit(*psz--);
- if (psz >= pbegin)
- {
- *p1 |= ((unsigned char)::HexDigit(*psz--) << 4);
- p1++;
- }
- }
- }
-
- void SetHex(const std::string& str)
- {
- SetHex(str.c_str());
- }
-
- std::string ToString() const
- {
- return (GetHex());
- }
+ std::string GetHex() const;
+ void SetHex(const char* psz);
+ void SetHex(const std::string& str);
+ std::string ToString() const;
unsigned char* begin()
{
@@ -424,19 +256,7 @@ public:
// Returns the position of the highest bit set plus one, or zero if the
// value is zero.
- unsigned int bits() const
- {
- for (int pos = WIDTH-1; pos >= 0; pos--) {
- if (pn[pos]) {
- for (int bits = 31; bits > 0; bits--) {
- if (pn[pos] & 1<<bits)
- return 32*pos + bits + 1;
- }
- return 32*pos + 1;
- }
- }
- return 0;
- }
+ unsigned int bits() const;
uint64_t GetLow64() const
{
@@ -500,56 +320,8 @@ public:
// targets, which are unsigned 256bit quantities. Thus, all the
// complexities of the sign bit and using base 256 are probably an
// implementation accident.
- //
- // This implementation directly uses shifts instead of going
- // through an intermediate MPI representation.
- uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL)
- {
- int nSize = nCompact >> 24;
- uint32_t nWord = nCompact & 0x007fffff;
- if (nSize <= 3)
- {
- nWord >>= 8*(3-nSize);
- *this = nWord;
- }
- else
- {
- *this = nWord;
- *this <<= 8*(nSize-3);
- }
- if (pfNegative)
- *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
- if (pfOverflow)
- *pfOverflow = nWord != 0 && ((nSize > 34) ||
- (nWord > 0xff && nSize > 33) ||
- (nWord > 0xffff && nSize > 32));
- return *this;
- }
-
- uint32_t GetCompact(bool fNegative = false) const
- {
- int nSize = (bits() + 7) / 8;
- uint32_t nCompact = 0;
- if (nSize <= 3)
- nCompact = GetLow64() << 8*(3-nSize);
- else
- {
- uint256 bn = *this >> 8*(nSize-3);
- nCompact = bn.GetLow64();
- }
- // The 0x00800000 bit denotes the sign.
- // Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
- if (nCompact & 0x00800000)
- {
- nCompact >>= 8;
- nSize++;
- }
- assert((nCompact & ~0x007fffff) == 0);
- assert(nSize < 256);
- nCompact |= nSize << 24;
- nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
- return nCompact;
- }
+ uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL);
+ uint32_t GetCompact(bool fNegative = false) const;
};
#endif
diff --git a/src/util.cpp b/src/util.cpp
index 9e4b2b787e..5a8f85ade7 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -77,11 +77,12 @@
// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
namespace boost {
+
namespace program_options {
std::string to_internal(const std::string&);
}
-}
+} // namespace boost
using namespace std;
@@ -419,6 +420,11 @@ 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, };
+signed char HexDigit(char c)
+{
+ return p_util_hexdigit[(unsigned char)c];
+}
+
bool IsHex(const string& str)
{
BOOST_FOREACH(char c, str)
diff --git a/src/util.h b/src/util.h
index 6057c72e66..707b8f2d76 100644
--- a/src/util.h
+++ b/src/util.h
@@ -156,6 +156,7 @@ 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);