aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/addrman.h2
-rw-r--r--src/ecwrapper.cpp33
-rw-r--r--src/leveldbwrapper.cpp3
-rw-r--r--src/limitedmap.h19
-rw-r--r--src/main.cpp2
-rw-r--r--src/merkleblock.cpp2
-rw-r--r--src/miner.cpp6
-rw-r--r--src/net.cpp2
-rw-r--r--src/net.h2
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/policy/fees.cpp2
-rw-r--r--src/policy/fees.h2
-rw-r--r--src/qt/paymentserver.cpp2
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/rest.cpp56
-rw-r--r--src/rpcblockchain.cpp97
-rw-r--r--src/rpcmining.cpp6
-rw-r--r--src/rpcserver.cpp4
-rw-r--r--src/scheduler.cpp12
-rw-r--r--src/script/interpreter.cpp2
-rw-r--r--src/sync.h2
-rw-r--r--src/test/data/tx_invalid.json4
-rw-r--r--src/test/data/tx_valid.json2
-rw-r--r--src/test/limitedmap_tests.cpp101
-rw-r--r--src/wallet/rpcwallet.cpp2
27 files changed, 287 insertions, 85 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 8289198959..fc4e047c35 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -52,6 +52,7 @@ BITCOIN_TESTS =\
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/key_tests.cpp \
+ test/limitedmap_tests.cpp \
test/main_tests.cpp \
test/mempool_tests.cpp \
test/miner_tests.cpp \
diff --git a/src/addrman.h b/src/addrman.h
index 2623d89809..384b6cfdb9 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -265,7 +265,7 @@ public:
* Notice that vvTried, mapAddr and vVector are never encoded explicitly;
* they are instead reconstructed from the other information.
*
- * vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
+ * vvNew is serialized, but only used if ADDRMAN_UNKNOWN_BUCKET_COUNT didn't change,
* otherwise it is reconstructed as well.
*
* This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp
index 5e3aec25ba..f94bc954fd 100644
--- a/src/ecwrapper.cpp
+++ b/src/ecwrapper.cpp
@@ -13,6 +13,29 @@
namespace {
+class ecgroup_order
+{
+public:
+ static const EC_GROUP* get()
+ {
+ static const ecgroup_order wrapper;
+ return wrapper.pgroup;
+ }
+
+private:
+ ecgroup_order()
+ : pgroup(EC_GROUP_new_by_curve_name(NID_secp256k1))
+ {
+ }
+
+ ~ecgroup_order()
+ {
+ EC_GROUP_free(pgroup);
+ }
+
+ EC_GROUP* pgroup;
+};
+
/**
* Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
* recid selects which key is recovered
@@ -92,8 +115,10 @@ err:
} // anon namespace
CECKey::CECKey() {
- pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+ pkey = EC_KEY_new();
assert(pkey != NULL);
+ int result = EC_KEY_set_group(pkey, ecgroup_order::get());
+ assert(result);
}
CECKey::~CECKey() {
@@ -185,11 +210,9 @@ bool CECKey::TweakPublic(const unsigned char vchTweak[32]) {
bool CECKey::SanityCheck()
{
- EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
- if(pkey == NULL)
+ const EC_GROUP *pgroup = ecgroup_order::get();
+ if(pgroup == NULL)
return false;
- EC_KEY_free(pkey);
-
// TODO Is there more EC functionality that could be missing?
return true;
}
diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp
index c353dfa6d9..26cacf95ae 100644
--- a/src/leveldbwrapper.cpp
+++ b/src/leveldbwrapper.cpp
@@ -58,7 +58,8 @@ CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCa
} else {
if (fWipe) {
LogPrintf("Wiping LevelDB in %s\n", path.string());
- leveldb::DestroyDB(path.string(), options);
+ leveldb::Status result = leveldb::DestroyDB(path.string(), options);
+ HandleError(result);
}
TryCreateDirectory(path);
LogPrintf("Opening LevelDB in %s\n", path.string());
diff --git a/src/limitedmap.h b/src/limitedmap.h
index e8ea549653..5456dfc7c4 100644
--- a/src/limitedmap.h
+++ b/src/limitedmap.h
@@ -27,7 +27,11 @@ protected:
size_type nMaxSize;
public:
- limitedmap(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; }
+ limitedmap(size_type nMaxSizeIn)
+ {
+ assert(nMaxSizeIn > 0);
+ nMaxSize = nMaxSizeIn;
+ }
const_iterator begin() const { return map.begin(); }
const_iterator end() const { return map.end(); }
size_type size() const { return map.size(); }
@@ -38,13 +42,12 @@ public:
{
std::pair<iterator, bool> ret = map.insert(x);
if (ret.second) {
- if (nMaxSize && map.size() == nMaxSize) {
+ if (map.size() > nMaxSize) {
map.erase(rmap.begin()->second);
rmap.erase(rmap.begin());
}
rmap.insert(make_pair(x.second, ret.first));
}
- return;
}
void erase(const key_type& k)
{
@@ -81,11 +84,11 @@ public:
size_type max_size() const { return nMaxSize; }
size_type max_size(size_type s)
{
- if (s)
- while (map.size() > s) {
- map.erase(rmap.begin()->second);
- rmap.erase(rmap.begin());
- }
+ assert(s > 0);
+ while (map.size() > s) {
+ map.erase(rmap.begin()->second);
+ rmap.erase(rmap.begin());
+ }
nMaxSize = s;
return nMaxSize;
}
diff --git a/src/main.cpp b/src/main.cpp
index 9f42819a0a..33b57a5285 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1457,7 +1457,7 @@ bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(
- userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage,
+ userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage,
"", CClientUIInterface::MSG_ERROR);
StartShutdown();
return false;
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 4d90fd8cd7..f8e877df25 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -168,7 +168,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
// traverse the partial tree
unsigned int nBitsUsed = 0, nHashUsed = 0;
uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
- // verify that no problems occured during the tree traversal
+ // verify that no problems occurred during the tree traversal
if (fBad)
return uint256();
// verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
diff --git a/src/miner.cpp b/src/miner.cpp
index 4172266067..9dd1d459b5 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -444,8 +444,10 @@ void static BitcoinMiner(const CChainParams& chainparams)
GetMainSignals().ScriptForMining(coinbaseScript);
try {
- //throw an error if no script was provided
- if (!coinbaseScript->reserveScript.size())
+ // Throw an error if no script was provided. This can happen
+ // due to some internal error but also if the keypool is empty.
+ // In the latter case, already the pointer is NULL.
+ if (!coinbaseScript || coinbaseScript->reserveScript.empty())
throw std::runtime_error("No coinbase script available (mining requires a wallet)");
while (true) {
diff --git a/src/net.cpp b/src/net.cpp
index e4ead3c92e..fb5726a2b9 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2319,7 +2319,7 @@ void DumpBanlist()
{
int64_t nStart = GetTimeMillis();
- CNode::SweepBanned(); //clean unused entires (if bantime has expired)
+ CNode::SweepBanned(); //clean unused entries (if bantime has expired)
CBanDB bandb;
banmap_t banmap;
diff --git a/src/net.h b/src/net.h
index efa2e29bb5..954cdd49d6 100644
--- a/src/net.h
+++ b/src/net.h
@@ -695,7 +695,7 @@ public:
static bool BannedSetIsDirty();
//!set the "dirty" flag for the banlist
static void SetBannedSetDirty(bool dirty=true);
- //!clean unused entires (if bantime has expired)
+ //!clean unused entries (if bantime has expired)
static void SweepBanned();
void copyStats(CNodeStats &stats);
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 259e5c14a3..7a87d125c2 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -349,7 +349,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
}
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
CloseSocket(hSocket);
- return error("Proxy authentication unsuccesful");
+ return error("Proxy authentication unsuccessful");
}
} else if (pchRet1[1] == 0x00) {
// Perform no authentication
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index cdee541d2f..ffe31d1942 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -261,7 +261,7 @@ void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHe
blocksAgo = 0;
if (blocksAgo < 0) {
LogPrint("estimatefee", "Blockpolicy error, blocks ago is negative for mempool tx\n");
- return; //This can't happen becasue we call this with our best seen height, no entries can have higher
+ return; //This can't happen because we call this with our best seen height, no entries can have higher
}
if (blocksAgo >= (int)unconfTxs.size()) {
diff --git a/src/policy/fees.h b/src/policy/fees.h
index ce4d782566..15577d128a 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -118,7 +118,7 @@ public:
/**
* Initialize the data structures. This is called by BlockPolicyEstimator's
* constructor with default values.
- * @param defaultBuckets contains the upper limits for the bucket boundries
+ * @param defaultBuckets contains the upper limits for the bucket boundaries
* @param maxConfirms max number of confirms to track
* @param decay how much to decay the historical moving average per block
* @param dataTypeString for logging purposes
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 0827d99125..5cc4d00dbf 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -762,7 +762,7 @@ void PaymentServer::setOptionsModel(OptionsModel *optionsModel)
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
{
- // currently we don't futher process or store the paymentACK message
+ // currently we don't further process or store the paymentACK message
Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
}
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 35729bbb8b..d9d4f1d0ed 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -570,7 +570,7 @@ void RPCConsole::peerLayoutChanged()
if (detailNodeRow < 0)
{
- // detail node dissapeared from table (node disconnected)
+ // detail node disappeared from table (node disconnected)
fUnselect = true;
}
else
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 8430e017c1..c15b64c327 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -57,7 +57,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
QPainter pixPaint(&pixmap);
pixPaint.setPen(QColor(100,100,100));
- // draw a slighly radial gradient
+ // draw a slightly radial gradient
QRadialGradient gradient(QPoint(0,0), splashSize.width()/devicePixelRatio);
gradient.setColorAt(0, Qt::white);
gradient.setColorAt(1, QColor(247,247,247));
diff --git a/src/rest.cpp b/src/rest.cpp
index 0dd238b683..74d27e73bb 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -65,6 +65,8 @@ public:
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
+extern UniValue mempoolInfoToJSON();
+extern UniValue mempoolToJSON(bool fVerbose = false);
extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
extern UniValue blockheaderToJSON(const CBlockIndex* blockindex);
@@ -293,6 +295,58 @@ static bool rest_chaininfo(AcceptedConnection* conn,
return true; // continue to process further HTTP reqs on this cxn
}
+static bool rest_mempool_info(AcceptedConnection* conn,
+ const std::string& strURIPart,
+ const std::string& strRequest,
+ const std::map<std::string, std::string>& mapHeaders,
+ bool fRun)
+{
+ vector<string> params;
+ const RetFormat rf = ParseDataFormat(params, strURIPart);
+
+ switch (rf) {
+ case RF_JSON: {
+ UniValue mempoolInfoObject = mempoolInfoToJSON();
+
+ string strJSON = mempoolInfoObject.write() + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ default: {
+ throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
+static bool rest_mempool_contents(AcceptedConnection* conn,
+ const std::string& strURIPart,
+ const std::string& strRequest,
+ const std::map<std::string, std::string>& mapHeaders,
+ bool fRun)
+{
+ vector<string> params;
+ const RetFormat rf = ParseDataFormat(params, strURIPart);
+
+ switch (rf) {
+ case RF_JSON: {
+ UniValue mempoolObject = mempoolToJSON(true);
+
+ string strJSON = mempoolObject.write() + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ default: {
+ throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
static bool rest_tx(AcceptedConnection* conn,
const std::string& strURIPart,
const std::string& strRequest,
@@ -553,6 +607,8 @@ static const struct {
{"/rest/block/notxdetails/", rest_block_notxdetails},
{"/rest/block/", rest_block_extended},
{"/rest/chaininfo", rest_chaininfo},
+ {"/rest/mempool/info", rest_mempool_info},
+ {"/rest/mempool/contents", rest_mempool_contents},
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
};
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 80d49490d2..e6751de96b 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -175,45 +175,8 @@ UniValue getdifficulty(const UniValue& params, bool fHelp)
return GetDifficulty();
}
-
-UniValue getrawmempool(const UniValue& params, bool fHelp)
+UniValue mempoolToJSON(bool fVerbose = false)
{
- if (fHelp || params.size() > 1)
- throw runtime_error(
- "getrawmempool ( verbose )\n"
- "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
- "\nArguments:\n"
- "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
- "\nResult: (for verbose = false):\n"
- "[ (json array of string)\n"
- " \"transactionid\" (string) The transaction id\n"
- " ,...\n"
- "]\n"
- "\nResult: (for verbose = true):\n"
- "{ (json object)\n"
- " \"transactionid\" : { (json object)\n"
- " \"size\" : n, (numeric) transaction size in bytes\n"
- " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
- " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
- " \"height\" : n, (numeric) block height when transaction entered pool\n"
- " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
- " \"currentpriority\" : n, (numeric) transaction priority now\n"
- " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
- " \"transactionid\", (string) parent transaction id\n"
- " ... ]\n"
- " }, ...\n"
- "}\n"
- "\nExamples\n"
- + HelpExampleCli("getrawmempool", "true")
- + HelpExampleRpc("getrawmempool", "true")
- );
-
- LOCK(cs_main);
-
- bool fVerbose = false;
- if (params.size() > 0)
- fVerbose = params[0].get_bool();
-
if (fVerbose)
{
LOCK(mempool.cs);
@@ -261,6 +224,47 @@ UniValue getrawmempool(const UniValue& params, bool fHelp)
}
}
+UniValue getrawmempool(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() > 1)
+ throw runtime_error(
+ "getrawmempool ( verbose )\n"
+ "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
+ "\nArguments:\n"
+ "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
+ "\nResult: (for verbose = false):\n"
+ "[ (json array of string)\n"
+ " \"transactionid\" (string) The transaction id\n"
+ " ,...\n"
+ "]\n"
+ "\nResult: (for verbose = true):\n"
+ "{ (json object)\n"
+ " \"transactionid\" : { (json object)\n"
+ " \"size\" : n, (numeric) transaction size in bytes\n"
+ " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
+ " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
+ " \"height\" : n, (numeric) block height when transaction entered pool\n"
+ " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
+ " \"currentpriority\" : n, (numeric) transaction priority now\n"
+ " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
+ " \"transactionid\", (string) parent transaction id\n"
+ " ... ]\n"
+ " }, ...\n"
+ "}\n"
+ "\nExamples\n"
+ + HelpExampleCli("getrawmempool", "true")
+ + HelpExampleRpc("getrawmempool", "true")
+ );
+
+ LOCK(cs_main);
+
+ bool fVerbose = false;
+ if (params.size() > 0)
+ fVerbose = params[0].get_bool();
+
+ return mempoolToJSON(fVerbose);
+}
+
UniValue getblockhash(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -757,6 +761,16 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
return res;
}
+UniValue mempoolInfoToJSON()
+{
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("size", (int64_t) mempool.size()));
+ ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
+ ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
+
+ return ret;
+}
+
UniValue getmempoolinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -774,12 +788,7 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getmempoolinfo", "")
);
- UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("size", (int64_t) mempool.size()));
- ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
- ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
-
- return ret;
+ return mempoolInfoToJSON();
}
UniValue invalidateblock(const UniValue& params, bool fHelp)
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index b7d4ff58fc..620a46be15 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -138,8 +138,12 @@ UniValue generate(const UniValue& params, bool fHelp)
boost::shared_ptr<CReserveScript> coinbaseScript;
GetMainSignals().ScriptForMining(coinbaseScript);
+ // If the keypool is exhausted, no script is returned at all. Catch this.
+ if (!coinbaseScript)
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+
//throw an error if no script was provided
- if (!coinbaseScript->reserveScript.size())
+ if (coinbaseScript->reserveScript.empty())
throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
{ // Don't keep cs_main locked
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 4088f374f8..9362401b1e 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -607,7 +607,7 @@ void StartRPCThreads()
LogPrintf("No rpcpassword set - using random cookie authentication\n");
if (!GenerateAuthCookie(&strRPCUserColonPass)) {
uiInterface.ThreadSafeMessageBox(
- _("Error: A fatal internal error occured, see debug.log for details"), // Same message as AbortNode
+ _("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode
"", CClientUIInterface::MSG_ERROR);
StartShutdown();
return;
@@ -671,7 +671,7 @@ void StartRPCThreads()
vEndpoints.push_back(ip::tcp::endpoint(boost::asio::ip::address_v6::any(), defaultPort));
vEndpoints.push_back(ip::tcp::endpoint(boost::asio::ip::address_v4::any(), defaultPort));
// Prefer making the socket dual IPv6/IPv4 instead of binding
- // to both addresses seperately.
+ // to both addresses separately.
bBindAny = true;
}
diff --git a/src/scheduler.cpp b/src/scheduler.cpp
index d5bb588b71..06115f5619 100644
--- a/src/scheduler.cpp
+++ b/src/scheduler.cpp
@@ -6,6 +6,7 @@
#include <assert.h>
#include <boost/bind.hpp>
+#include <boost/thread/reverse_lock.hpp>
#include <utility>
CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
@@ -65,11 +66,12 @@ void CScheduler::serviceQueue()
Function f = taskQueue.begin()->second;
taskQueue.erase(taskQueue.begin());
- // Unlock before calling f, so it can reschedule itself or another task
- // without deadlocking:
- lock.unlock();
- f();
- lock.lock();
+ {
+ // Unlock before calling f, so it can reschedule itself or another task
+ // without deadlocking:
+ boost::reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ f();
+ }
} catch (...) {
--nThreadsServicingQueue;
throw;
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 0b78fdf5a8..bd5e54b33f 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1128,7 +1128,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
{
- // There are two times of nLockTime: lock-by-blockheight
+ // There are two kinds of nLockTime: lock-by-blockheight
// and lock-by-blocktime, distinguished by whether
// nLockTime < LOCKTIME_THRESHOLD.
//
diff --git a/src/sync.h b/src/sync.h
index 705647e4a5..68a9443084 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -16,7 +16,7 @@
////////////////////////////////////////////////
// //
-// THE SIMPLE DEFINITON, EXCLUDING DEBUG CODE //
+// THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
// //
////////////////////////////////////////////////
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 20bdbd08a5..5cad5af7c3 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -128,7 +128,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"],
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 NOP2 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
@@ -181,7 +181,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"],
-["6 byte non-minimally-encoded arguments are invalid even in their contents are valid"],
+["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP2 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 24fff575c1..9744a3c848 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -197,7 +197,7 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
-["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"],
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]],
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
new file mode 100644
index 0000000000..faaddffad8
--- /dev/null
+++ b/src/test/limitedmap_tests.cpp
@@ -0,0 +1,101 @@
+// Copyright (c) 2012-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "limitedmap.h"
+
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(limitedmap_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(limitedmap_test)
+{
+ // create a limitedmap capped at 10 items
+ limitedmap<int, int> map(10);
+
+ // check that the max size is 10
+ BOOST_CHECK(map.max_size() == 10);
+
+ // check that it's empty
+ BOOST_CHECK(map.size() == 0);
+
+ // insert (-1, -1)
+ map.insert(std::pair<int, int>(-1, -1));
+
+ // make sure that the size is updated
+ BOOST_CHECK(map.size() == 1);
+
+ // make sure that the new items is in the map
+ BOOST_CHECK(map.count(-1) == 1);
+
+ // insert 10 new items
+ for (int i = 0; i < 10; i++) {
+ map.insert(std::pair<int, int>(i, i + 1));
+ }
+
+ // make sure that the map now contains 10 items...
+ BOOST_CHECK(map.size() == 10);
+
+ // ...and that the first item has been discarded
+ BOOST_CHECK(map.count(-1) == 0);
+
+ // iterate over the map, both with an index and an iterator
+ limitedmap<int, int>::const_iterator it = map.begin();
+ for (int i = 0; i < 10; i++) {
+ // make sure the item is present
+ BOOST_CHECK(map.count(i) == 1);
+
+ // use the iterator to check for the expected key adn value
+ BOOST_CHECK(it->first == i);
+ BOOST_CHECK(it->second == i + 1);
+
+ // use find to check for the value
+ BOOST_CHECK(map.find(i)->second == i + 1);
+
+ // update and recheck
+ map.update(it, i + 2);
+ BOOST_CHECK(map.find(i)->second == i + 2);
+
+ it++;
+ }
+
+ // check that we've exhausted the iterator
+ BOOST_CHECK(it == map.end());
+
+ // resize the map to 5 items
+ map.max_size(5);
+
+ // check that the max size and size are now 5
+ BOOST_CHECK(map.max_size() == 5);
+ BOOST_CHECK(map.size() == 5);
+
+ // check that items less than 5 have been discarded
+ // and items greater than 5 are retained
+ for (int i = 0; i < 10; i++) {
+ if (i < 5) {
+ BOOST_CHECK(map.count(i) == 0);
+ } else {
+ BOOST_CHECK(map.count(i) == 1);
+ }
+ }
+
+ // erase some items not in the map
+ for (int i = 100; i < 1000; i += 100) {
+ map.erase(i);
+ }
+
+ // check that the size is unaffected
+ BOOST_CHECK(map.size() == 5);
+
+ // erase the remaining elements
+ for (int i = 5; i < 10; i++) {
+ map.erase(i);
+ }
+
+ // check that the map is now empty
+ BOOST_CHECK(map.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index bd16da7614..5d182f3d42 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -797,7 +797,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
"4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
"5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n"
"\nResult:\n"
- "true|false (boolean) true if successfull.\n"
+ "true|false (boolean) true if successful.\n"
"\nExamples:\n"
"\nMove 0.01 " + CURRENCY_UNIT + " from the default account to the account named tabby\n"
+ HelpExampleCli("move", "\"\" \"tabby\" 0.01") +