aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init.cpp4
-rw-r--r--src/main.h4
-rw-r--r--src/miner.cpp2
-rw-r--r--src/primitives/transaction.cpp9
-rw-r--r--src/primitives/transaction.h3
-rw-r--r--src/qt/optionsdialog.cpp2
-rw-r--r--src/rest.cpp2
-rw-r--r--src/rpcblockchain.cpp82
-rw-r--r--src/rpcclient.cpp1
-rw-r--r--src/rpcserver.cpp1
-rw-r--r--src/rpcserver.h1
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/util.cpp10
-rw-r--r--src/util.h7
-rw-r--r--src/wallet/wallet.cpp1
15 files changed, 123 insertions, 8 deletions
diff --git a/src/init.cpp b/src/init.cpp
index b9510bec9d..94bf5eb2f4 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -283,7 +283,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file") + " " + _("on startup"));
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
- -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
+ -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
#ifndef WIN32
strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), "bitcoind.pid"));
#endif
@@ -772,7 +772,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (nScriptCheckThreads <= 0)
- nScriptCheckThreads += boost::thread::hardware_concurrency();
+ nScriptCheckThreads += GetNumCores();
if (nScriptCheckThreads <= 1)
nScriptCheckThreads = 0;
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
diff --git a/src/main.h b/src/main.h
index 4e2efaada0..43bc4031f1 100644
--- a/src/main.h
+++ b/src/main.h
@@ -131,7 +131,7 @@ extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
-static const signed int MIN_BLOCKS_TO_KEEP = 288;
+static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.
@@ -141,7 +141,7 @@ static const signed int MIN_BLOCKS_TO_KEEP = 288;
// full block file chunks, we need the high water mark which triggers the prune to be
// one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB
// Setting the target to > than 550MB will make it likely we can respect the target.
-static const signed int MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
+static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
diff --git a/src/miner.cpp b/src/miner.cpp
index 2c5cba742c..ca32e9f7b3 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -546,7 +546,7 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar
if (Params().DefaultMinerThreads())
nThreads = Params().DefaultMinerThreads();
else
- nThreads = boost::thread::hardware_concurrency();
+ nThreads = GetNumCores();
}
if (minerThreads != NULL)
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 606dbea798..d864a9b6d3 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -87,6 +87,15 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
return *this;
}
+bool CTransaction::IsEquivalentTo(const CTransaction& tx) const
+{
+ CMutableTransaction tx1 = *this;
+ CMutableTransaction tx2 = tx;
+ for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript();
+ for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript();
+ return CTransaction(tx1) == CTransaction(tx2);
+}
+
CAmount CTransaction::GetValueOut() const
{
CAmount nValueOut = 0;
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 6cfd93a9a1..0c9ebb7b88 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -222,6 +222,9 @@ public:
return hash;
}
+ // True if only scriptSigs are different
+ bool IsEquivalentTo(const CTransaction& tx) const;
+
// Return sum of txouts.
CAmount GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index efb2bf4158..87c727335e 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -42,7 +42,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
/* Main elements init */
ui->databaseCache->setMinimum(nMinDbCache);
ui->databaseCache->setMaximum(nMaxDbCache);
- ui->threadsScriptVerif->setMinimum(-(int)boost::thread::hardware_concurrency());
+ ui->threadsScriptVerif->setMinimum(-GetNumCores());
ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
/* Network elements init */
diff --git a/src/rest.cpp b/src/rest.cpp
index 1fce7dfc9c..a1bd893bec 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -20,7 +20,7 @@
using namespace std;
-static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
+static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
enum RetFormat {
RF_UNDEF,
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 0b34225d8f..b7c3eb1724 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -51,6 +51,32 @@ double GetDifficulty(const CBlockIndex* blockindex)
return dDiff;
}
+UniValue blockheaderToJSON(const CBlockIndex* blockindex)
+{
+ UniValue result(UniValue::VOBJ);
+ result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
+ int confirmations = -1;
+ // Only report confirmations if the block is on the main chain
+ if (chainActive.Contains(blockindex))
+ confirmations = chainActive.Height() - blockindex->nHeight + 1;
+ result.push_back(Pair("confirmations", confirmations));
+ result.push_back(Pair("height", blockindex->nHeight));
+ result.push_back(Pair("version", blockindex->nVersion));
+ result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
+ result.push_back(Pair("time", (int64_t)blockindex->nTime));
+ result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
+ result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
+ result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
+ result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
+
+ if (blockindex->pprev)
+ result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
+ CBlockIndex *pnext = chainActive.Next(blockindex);
+ if (pnext)
+ result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
+ return result;
+}
+
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
@@ -255,6 +281,62 @@ UniValue getblockhash(const UniValue& params, bool fHelp)
return pblockindex->GetBlockHash().GetHex();
}
+UniValue getblockheader(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 2)
+ throw runtime_error(
+ "getblockheader \"hash\" ( verbose )\n"
+ "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
+ "If verbose is true, returns an Object with information about blockheader <hash>.\n"
+ "\nArguments:\n"
+ "1. \"hash\" (string, required) The block hash\n"
+ "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
+ "\nResult (for verbose = true):\n"
+ "{\n"
+ " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
+ " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
+ " \"height\" : n, (numeric) The block height or index\n"
+ " \"version\" : n, (numeric) The block version\n"
+ " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
+ " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"nonce\" : n, (numeric) The nonce\n"
+ " \"bits\" : \"1d00ffff\", (string) The bits\n"
+ " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
+ " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
+ " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
+ "}\n"
+ "\nResult (for verbose=false):\n"
+ "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ );
+
+ LOCK(cs_main);
+
+ std::string strHash = params[0].get_str();
+ uint256 hash(uint256S(strHash));
+
+ bool fVerbose = true;
+ if (params.size() > 1)
+ fVerbose = params[1].get_bool();
+
+ if (mapBlockIndex.count(hash) == 0)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+
+ CBlockIndex* pblockindex = mapBlockIndex[hash];
+
+ if (!fVerbose)
+ {
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ ssBlock << pblockindex->GetBlockHeader();
+ std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
+ return strHex;
+ }
+
+ return blockheaderToJSON(pblockindex);
+}
+
UniValue getblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index 4c6b47e4a0..b41e960e8a 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -71,6 +71,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 1 },
{ "listunspent", 2 },
{ "getblock", 1 },
+ { "getblockheader", 1 },
{ "gettransaction", 1 },
{ "getrawtransaction", 1 },
{ "createrawtransaction", 0 },
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index b76575fc4a..287cfb2f13 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -289,6 +289,7 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "getblockcount", &getblockcount, true },
{ "blockchain", "getblock", &getblock, true },
{ "blockchain", "getblockhash", &getblockhash, true },
+ { "blockchain", "getblockheader", &getblockheader, true },
{ "blockchain", "getchaintips", &getchaintips, true },
{ "blockchain", "getdifficulty", &getdifficulty, true },
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true },
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 45af10c2a8..89d3980223 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -234,6 +234,7 @@ extern UniValue settxfee(const UniValue& params, bool fHelp);
extern UniValue getmempoolinfo(const UniValue& params, bool fHelp);
extern UniValue getrawmempool(const UniValue& params, bool fHelp);
extern UniValue getblockhash(const UniValue& params, bool fHelp);
+extern UniValue getblockheader(const UniValue& params, bool fHelp);
extern UniValue getblock(const UniValue& params, bool fHelp);
extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp);
extern UniValue gettxout(const UniValue& params, bool fHelp);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 1c16e2092e..2292191be4 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -166,7 +166,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in
continue;
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
if (fSanityCheck) assert(coins);
- if (!coins || (coins->IsCoinBase() && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) {
+ if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
transactionsToRemove.push_back(tx);
break;
}
diff --git a/src/util.cpp b/src/util.cpp
index da5821e530..bb7df23205 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -756,3 +756,13 @@ void SetThreadPriority(int nPriority)
#endif // PRIO_THREAD
#endif // WIN32
}
+
+int GetNumCores()
+{
+#if BOOST_VERSION >= 105600
+ return boost::thread::physical_concurrency();
+#else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores
+ return boost::thread::hardware_concurrency();
+#endif
+}
+
diff --git a/src/util.h b/src/util.h
index 6ec81698ea..6019e25015 100644
--- a/src/util.h
+++ b/src/util.h
@@ -199,6 +199,13 @@ std::string HelpMessageGroup(const std::string& message);
*/
std::string HelpMessageOpt(const std::string& option, const std::string& message);
+/**
+ * Return the number of physical cores available on the current system.
+ * @note This does not count virtual cores, such as those provided by HyperThreading
+ * when boost is newer than 1.56.
+ */
+int GetNumCores();
+
void SetThreadPriority(int nPriority);
void RenameThread(const char* name);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 238f62a575..44e28de0cd 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -419,6 +419,7 @@ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
const uint256& hash = it->second;
CWalletTx* copyTo = &mapWallet[hash];
if (copyFrom == copyTo) continue;
+ if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
copyTo->mapValue = copyFrom->mapValue;
copyTo->vOrderForm = copyFrom->vOrderForm;
// fTimeReceivedIsTxTime not copied on purpose