aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bench/block_assemble.cpp12
-rw-r--r--src/bench/coin_selection.cpp2
-rw-r--r--src/bench/mempool_eviction.cpp3
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/chainparams.cpp25
-rw-r--r--src/chainparams.h6
-rw-r--r--src/httpserver.cpp9
-rw-r--r--src/httpserver.h2
-rw-r--r--src/init.cpp8
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/miner.cpp4
-rw-r--r--src/net.cpp3
-rw-r--r--src/net.h2
-rw-r--r--src/netaddress.cpp3
-rw-r--r--src/rpc/server.cpp3
-rw-r--r--src/rpc/server.h2
-rw-r--r--src/scheduler.h17
-rw-r--r--src/script/interpreter.cpp6
-rw-r--r--src/test/blockencodings_tests.cpp6
-rw-r--r--src/test/mempool_tests.cpp7
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/policyestimator_tests.cpp1
-rw-r--r--src/test/scheduler_tests.cpp44
-rw-r--r--src/torcontrol.cpp5
-rw-r--r--src/txdb.cpp3
-rw-r--r--src/txdb.h2
-rw-r--r--src/txmempool.cpp10
-rw-r--r--src/txmempool.h6
-rw-r--r--src/util.cpp10
-rw-r--r--src/validation.cpp8
-rw-r--r--src/validation.h2
-rw-r--r--src/validationinterface.h15
-rw-r--r--src/wallet/wallet.cpp50
-rw-r--r--src/wallet/wallet.h14
-rw-r--r--src/wallet/walletdb.cpp12
35 files changed, 180 insertions, 129 deletions
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 36fa175a76..9b53c6b023 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -97,10 +97,14 @@ static void AssembleBlock(benchmark::State& state)
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
txs.at(b) = MakeTransactionRef(tx);
}
- for (const auto& txr : txs) {
- CValidationState state;
- bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
- assert(ret);
+ {
+ LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
+
+ for (const auto& txr : txs) {
+ CValidationState state;
+ bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
+ assert(ret);
+ }
}
while (state.KeepRunning()) {
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 7510d53c88..20013d702b 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -21,7 +21,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<Ou
int nAge = 6 * 24;
COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
- groups.emplace_back(output.GetInputCoin(), 0, false, 0, 0);
+ groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
}
// Simple benchmark for wallet coin selection. Note that it maybe be necessary
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 4c947a519f..d37291b900 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -9,7 +9,7 @@
#include <list>
#include <vector>
-static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool)
+static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
{
int64_t nTime = 0;
unsigned int nHeight = 1;
@@ -108,6 +108,7 @@ static void MempoolEviction(benchmark::State& state)
tx7.vout[1].nValue = 10 * COIN;
CTxMemPool pool;
+ LOCK(pool.cs);
// Create transaction references outside the "hot loop"
const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 5c711c0773..4d010c0d14 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -96,7 +96,7 @@ static bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return false;
}
- if (!gArgs.ReadConfigFiles(error)) {
+ if (!gArgs.ReadConfigFiles(error, true)) {
fprintf(stderr, "Error reading configuration file: %s\n", error.c_str());
return false;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 71762158f0..b517717c97 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -102,10 +102,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000f91c579d57cad4bc5278cc");
+ consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000028822fef1c230963535a90d");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000000000000005214481d2d96f898e3d5416e43359c145944a909d242e0"); //506067
+ consensus.defaultAssumeValid = uint256S("0x0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8"); //534292
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -170,11 +170,10 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 0000000000000000002d6cca6761c99b3c2e936f9a0e304b7c7651a993f461de (height 506081).
- 1516903077, // * UNIX timestamp of last known number of transactions
- 295363220, // * total number of transactions between genesis and that timestamp
- // (the tx=... number in the ChainStateFlushed debug.log lines)
- 3.5 // * estimated number of transactions per second after that timestamp
+ // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8
+ /* nTime */ 1532884444,
+ /* nTxCount */ 331282217,
+ /* dTxRate */ 2.4
};
/* disable fallback fee on mainnet */
@@ -217,10 +216,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000002830dab7f76dbb7d63");
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000007dbe94253893cbd463");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000002e9e7b00e1f6dc5123a04aad68dd0f0968d8c7aa45f6640795c37b1"); //1135275
+ consensus.defaultAssumeValid = uint256S("0x0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75"); //1354312
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -264,10 +263,10 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 000000000000033cfa3c975eb83ecf2bb4aaedf68e6d279f6ed2b427c64caff9 (height 1260526)
- 1516903490,
- 17082348,
- 0.09
+ // Data from rpc: getchaintxstats 4096 0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75
+ /* nTime */ 1531929919,
+ /* nTxCount */ 19438708,
+ /* dTxRate */ 0.626
};
/* enable fallback fee on testnet */
diff --git a/src/chainparams.h b/src/chainparams.h
index dd029b9d5b..344cbb1a8a 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -32,9 +32,9 @@ struct CCheckpointData {
* See also: CChainParams::TxData, GuessVerificationProgress.
*/
struct ChainTxData {
- int64_t nTime;
- int64_t nTxCount;
- double dTxRate;
+ int64_t nTime; //!< UNIX timestamp of last known number of transactions
+ int64_t nTxCount; //!< total number of transactions between genesis and that timestamp
+ double dTxRate; //!< estimated number of transactions per second after that timestamp
};
/**
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index bd08b04c0f..9daf3d1968 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -279,7 +279,7 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
}
/** Event dispatcher thread */
-static bool ThreadHTTP(struct event_base* base, struct evhttp* http)
+static bool ThreadHTTP(struct event_base* base)
{
RenameThread("bitcoin-http");
LogPrint(BCLog::HTTP, "Entering http event loop\n");
@@ -423,19 +423,18 @@ std::thread threadHTTP;
std::future<bool> threadResult;
static std::vector<std::thread> g_thread_http_workers;
-bool StartHTTPServer()
+void StartHTTPServer()
{
LogPrint(BCLog::HTTP, "Starting HTTP server\n");
int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
- std::packaged_task<bool(event_base*, evhttp*)> task(ThreadHTTP);
+ std::packaged_task<bool(event_base*)> task(ThreadHTTP);
threadResult = task.get_future();
- threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
+ threadHTTP = std::thread(std::move(task), eventBase);
for (int i = 0; i < rpcThreads; i++) {
g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
}
- return true;
}
void InterruptHTTPServer()
diff --git a/src/httpserver.h b/src/httpserver.h
index 8132c887b5..8a3adaf91f 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -26,7 +26,7 @@ bool InitHTTPServer();
* This is separate from InitHTTPServer to give users race-condition-free time
* to register their handlers between InitHTTPServer and StartHTTPServer.
*/
-bool StartHTTPServer();
+void StartHTTPServer();
/** Interrupt HTTP server threads */
void InterruptHTTPServer();
/** Stop HTTP server */
diff --git a/src/init.cpp b/src/init.cpp
index c7ea40817d..18402ef5d7 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -731,14 +731,12 @@ static bool AppInitServers()
RPCServer::OnStopped(&OnRPCStopped);
if (!InitHTTPServer())
return false;
- if (!StartRPC())
- return false;
+ StartRPC();
if (!StartHTTPRPC())
return false;
if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST())
return false;
- if (!StartHTTPServer())
- return false;
+ StartHTTPServer();
return true;
}
@@ -927,7 +925,7 @@ bool AppInitParameterInteraction()
// also see: InitParameterInteraction()
if (!fs::is_directory(GetBlocksDir(false))) {
- return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist.\n"), gArgs.GetArg("-blocksdir", "").c_str()));
+ return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
}
// if using block pruning, then disallow txindex
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index db371d104e..106dd38f60 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -53,7 +53,7 @@ class NodeImpl : public Node
{
return gArgs.ParseParameters(argc, argv, error);
}
- bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error); }
+ bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
diff --git a/src/miner.cpp b/src/miner.cpp
index 738ccad1b9..c32dc26f86 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -64,7 +64,7 @@ BlockAssembler::BlockAssembler(const CChainParams& params, const Options& option
nBlockMaxWeight = std::max<size_t>(4000, std::min<size_t>(MAX_BLOCK_WEIGHT - 4000, options.nBlockMaxWeight));
}
-static BlockAssembler::Options DefaultOptions(const CChainParams& params)
+static BlockAssembler::Options DefaultOptions()
{
// Block resource limits
// If -blockmaxweight is not given, limit to DEFAULT_BLOCK_MAX_WEIGHT
@@ -80,7 +80,7 @@ static BlockAssembler::Options DefaultOptions(const CChainParams& params)
return options;
}
-BlockAssembler::BlockAssembler(const CChainParams& params) : BlockAssembler(params, DefaultOptions(params)) {}
+BlockAssembler::BlockAssembler(const CChainParams& params) : BlockAssembler(params, DefaultOptions()) {}
void BlockAssembler::resetBlock()
{
diff --git a/src/net.cpp b/src/net.cpp
index 67a73fa9fc..0ebfefa757 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -235,12 +235,11 @@ bool AddLocal(const CNetAddr &addr, int nScore)
return AddLocal(CService(addr, GetListenPort()), nScore);
}
-bool RemoveLocal(const CService& addr)
+void RemoveLocal(const CService& addr)
{
LOCK(cs_mapLocalHost);
LogPrintf("RemoveLocal(%s)\n", addr.ToString());
mapLocalHost.erase(addr);
- return true;
}
/** Make a particular network entirely off-limits (no automatic connects to it) */
diff --git a/src/net.h b/src/net.h
index 607b2fc53c..36c2a4b8f5 100644
--- a/src/net.h
+++ b/src/net.h
@@ -505,7 +505,7 @@ bool IsLimited(enum Network net);
bool IsLimited(const CNetAddr& addr);
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
-bool RemoveLocal(const CService& addr);
+void RemoveLocal(const CService& addr);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = nullptr);
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 5ccbabd03d..193582d14e 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -300,6 +300,9 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
{
+ if (!IsIPv6()) {
+ return false;
+ }
memcpy(pipv6Addr, ip, 16);
return true;
}
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index b420e9d8b3..e46bf2f765 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -301,12 +301,11 @@ bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd)
return true;
}
-bool StartRPC()
+void StartRPC()
{
LogPrint(BCLog::RPC, "Starting RPC\n");
fRPCRunning = true;
g_rpcSignals.Started();
- return true;
}
void InterruptRPC()
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 373914885c..a9dbfbd21f 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -198,7 +198,7 @@ extern CAmount AmountFromValue(const UniValue& value);
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
-bool StartRPC();
+void StartRPC();
void InterruptRPC();
void StopRPC();
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);
diff --git a/src/scheduler.h b/src/scheduler.h
index 7169dceee5..421002ec17 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -86,9 +86,13 @@ private:
/**
* Class used by CScheduler clients which may schedule multiple jobs
- * which are required to be run serially. Does not require such jobs
- * to be executed on the same thread, but no two jobs will be executed
- * at the same time.
+ * which are required to be run serially. Jobs may not be run on the
+ * same thread, but no two jobs will be executed
+ * at the same time and memory will be release-acquire consistent
+ * (the scheduler will internally do an acquire before invoking a callback
+ * as well as a release at the end). In practice this means that a callback
+ * B() will be able to observe all of the effects of callback A() which executed
+ * before it.
*/
class SingleThreadedSchedulerClient {
private:
@@ -103,6 +107,13 @@ private:
public:
explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
+
+ /**
+ * Add a callback to be executed. Callbacks are executed serially
+ * and memory is sequentially consistent between callback executions.
+ * Practially, this means that callbacks can behave as if they are executed
+ * in order by a single thread.
+ */
void AddToProcessQueue(std::function<void (void)> func);
// Processes all remaining queue members on the calling thread, blocking until queue is empty
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 1936d44cd5..be2138d502 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1588,7 +1588,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
return set_success(serror);
}
-size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& witprogram, const CScriptWitness& witness, int flags)
+size_t static WitnessSigOps(int witversion, const std::vector<unsigned char>& witprogram, const CScriptWitness& witness)
{
if (witversion == 0) {
if (witprogram.size() == WITNESS_V0_KEYHASH_SIZE)
@@ -1616,7 +1616,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
int witnessversion;
std::vector<unsigned char> witnessprogram;
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
- return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty);
}
if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) {
@@ -1628,7 +1628,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
}
CScript subscript(data.begin(), data.end());
if (subscript.IsWitnessProgram(witnessversion, witnessprogram)) {
- return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty);
}
}
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 3dd5356164..df839884fe 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -62,8 +62,8 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
// Do a simple ShortTxIDs RT
@@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
@@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index e2d76dc293..fb80599af7 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -55,6 +55,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool;
+ LOCK(testPool.cs);
// Nothing in pool, remove should do nothing:
unsigned int poolSize = testPool.size();
@@ -119,6 +120,7 @@ static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) E
BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -165,7 +167,6 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder[2] = tx1.GetHash().ToString(); // 10000
sortedOrder[3] = tx4.GetHash().ToString(); // 15000
sortedOrder[4] = tx2.GetHash().ToString(); // 20000
- LOCK(pool.cs);
CheckSort<descendant_score>(pool, sortedOrder);
/* low fee but with high fee child */
@@ -292,6 +293,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -347,7 +349,6 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
}
sortedOrder[4] = tx3.GetHash().ToString(); // 0
- LOCK(pool.cs);
CheckSort<ancestor_score>(pool, sortedOrder);
/* low fee parent with high fee child */
@@ -421,6 +422,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
CMutableTransaction tx1 = CMutableTransaction();
@@ -593,6 +595,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
size_t ancestors, descendants;
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* Base transaction */
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 10c7fd00e8..e2424f012d 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -99,7 +99,7 @@ static bool TestSequenceLocks(const CTransaction &tx, int flags)
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
-static void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
+static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
}
LOCK(cs_main);
+ LOCK(::mempool.cs);
// Just to make sure we can still make simple blocks
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 8d288ec993..e45fb6d17e 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -18,6 +18,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
CBlockPolicyEstimator feeEst;
CTxMemPool mpool(&feeEst);
+ LOCK(mpool.cs);
TestMemPoolEntryHelper entry;
CAmount basefee(2000);
CAmount deltaFee(100);
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index 179df7dd38..b1ea4b6fab 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(manythreads)
size_t nTasks = microTasks.getQueueInfo(first, last);
BOOST_CHECK(nTasks == 0);
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < 100; ++i) {
boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
@@ -112,4 +112,46 @@ BOOST_AUTO_TEST_CASE(manythreads)
BOOST_CHECK_EQUAL(counterSum, 200);
}
+BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
+{
+ CScheduler scheduler;
+
+ // each queue should be well ordered with respect to itself but not other queues
+ SingleThreadedSchedulerClient queue1(&scheduler);
+ SingleThreadedSchedulerClient queue2(&scheduler);
+
+ // create more threads than queues
+ // if the queues only permit execution of one task at once then
+ // the extra threads should effectively be doing nothing
+ // if they don't we'll get out of order behaviour
+ boost::thread_group threads;
+ for (int i = 0; i < 5; ++i) {
+ threads.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ }
+
+ // these are not atomic, if SinglethreadedSchedulerClient prevents
+ // parallel execution at the queue level no synchronization should be required here
+ int counter1 = 0;
+ int counter2 = 0;
+
+ // just simply count up on each queue - if execution is properly ordered then
+ // the callbacks should run in exactly the order in which they were enqueued
+ for (int i = 0; i < 100; ++i) {
+ queue1.AddToProcessQueue([i, &counter1]() {
+ BOOST_CHECK_EQUAL(i, counter1++);
+ });
+
+ queue2.AddToProcessQueue([i, &counter2]() {
+ BOOST_CHECK_EQUAL(i, counter2++);
+ });
+ }
+
+ // finish up
+ scheduler.stop(true);
+ threads.join_all();
+
+ BOOST_CHECK_EQUAL(counter1, 100);
+ BOOST_CHECK_EQUAL(counter2, 100);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 1f42ab8fa8..fbc193c2cf 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -91,7 +91,7 @@ public:
/**
* Disconnect from Tor control port.
*/
- bool Disconnect();
+ void Disconnect();
/** Send a command, register a handler for the reply.
* A trailing CRLF is automatically added.
@@ -223,12 +223,11 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB
return true;
}
-bool TorControlConnection::Disconnect()
+void TorControlConnection::Disconnect()
{
if (b_conn)
bufferevent_free(b_conn);
b_conn = nullptr;
- return true;
}
bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB& reply_handler)
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 1fc7919442..cbea550739 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -160,9 +160,8 @@ bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
return Erase(DB_REINDEX_FLAG);
}
-bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
+void CBlockTreeDB::ReadReindexing(bool &fReindexing) {
fReindexing = Exists(DB_REINDEX_FLAG);
- return true;
}
bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
diff --git a/src/txdb.h b/src/txdb.h
index 100adb428d..84011097ce 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -92,7 +92,7 @@ public:
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info);
bool ReadLastBlockFile(int &nFile);
bool WriteReindexing(bool fReindexing);
- bool ReadReindexing(bool &fReindexing);
+ void ReadReindexing(bool &fReindexing);
bool WriteFlag(const std::string &name, bool fValue);
bool ReadFlag(const std::string &name, bool &fValue);
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 2108e6ba2d..d68c38ad4e 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -151,8 +151,6 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */) const
{
- LOCK(cs);
-
setEntries parentHashes;
const CTransaction &tx = entry.GetTx();
@@ -357,13 +355,12 @@ void CTxMemPool::AddTransactionsUpdated(unsigned int n)
nTransactionsUpdated += n;
}
-bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
+void CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
{
NotifyEntryAdded(entry.GetSharedTx());
// Add to memory pool without checking anything.
// Used by AcceptToMemoryPool(), which DOES do
// all the appropriate checks.
- LOCK(cs);
indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
mapLinks.insert(make_pair(newit, TxLinks()));
@@ -412,8 +409,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
vTxHashes.emplace_back(tx.GetWitnessHash(), newit);
newit->vTxHashesIdx = vTxHashes.size() - 1;
-
- return true;
}
void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
@@ -933,9 +928,8 @@ int CTxMemPool::Expire(int64_t time) {
return stage.size();
}
-bool CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool validFeeEstimate)
+void CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool validFeeEstimate)
{
- LOCK(cs);
setEntries setAncestors;
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
diff --git a/src/txmempool.h b/src/txmempool.h
index f3b8a68a9d..0feea08f0b 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -539,8 +539,8 @@ public:
// Note that addUnchecked is ONLY called from ATMP outside of tests
// and any other callers may break wallet's in-mempool tracking (due to
// lack of CValidationInterface::TransactionAddedToMempool callbacks).
- bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool validFeeEstimate = true);
- bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate = true);
+ void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
@@ -596,7 +596,7 @@ public:
* fSearchForParents = whether to search a tx's vin for in-mempool parents, or
* look up parents from mapLinks. Must be true for entries not in the mempool
*/
- bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true) const;
+ bool CalculateMemPoolAncestors(const CTxMemPoolEntry& entry, setEntries& setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string& errString, bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Populate setDescendants with all in-mempool descendants of hash.
* Assumes that setDescendants includes all in-mempool descendants of anything
diff --git a/src/util.cpp b/src/util.cpp
index 2f81f50a71..238554ee4a 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -859,9 +859,13 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, boo
}
// Check that the arg is known
- if (!IsArgKnown(strKey) && !ignore_invalid_keys) {
- error = strprintf("Invalid configuration value %s", option.first.c_str());
- return false;
+ if (!IsArgKnown(strKey)) {
+ if (!ignore_invalid_keys) {
+ error = strprintf("Invalid configuration value %s", option.first.c_str());
+ return false;
+ } else {
+ LogPrintf("Ignoring unknown configuration value %s\n", option.first);
+ }
}
}
return true;
diff --git a/src/validation.cpp b/src/validation.cpp
index f1b63b5b44..702a8d7e05 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -178,7 +178,7 @@ public:
// Manual block validity manipulation:
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
bool RewindBlockIndex(const CChainParams& params);
@@ -2882,7 +2882,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C
return g_chainstate.InvalidateBlock(state, chainparams, pindex);
}
-bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
+void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
AssertLockHeld(cs_main);
int nHeight = pindex->nHeight;
@@ -2914,9 +2914,9 @@ bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
}
pindex = pindex->pprev;
}
- return true;
}
-bool ResetBlockFailureFlags(CBlockIndex *pindex) {
+
+void ResetBlockFailureFlags(CBlockIndex *pindex) {
return g_chainstate.ResetBlockFailureFlags(pindex);
}
diff --git a/src/validation.h b/src/validation.h
index 1aff10f025..ce46a5a782 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -449,7 +449,7 @@ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIn
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Remove invalidity status from a block and its descendants. */
-bool ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** The currently-connected chain of blocks (protected by cs_main). */
extern CChain& chainActive;
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 42cc2e9a20..bddc28d24a 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -53,6 +53,21 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
*/
void SyncWithValidationInterfaceQueue();
+/**
+ * Implement this to subscribe to events generated in validation
+ *
+ * Each CValidationInterface() subscriber will receive event callbacks
+ * in the order in which the events were generated by validation.
+ * Furthermore, each ValidationInterface() subscriber may assume that
+ * callbacks effectively run in a single thread with single-threaded
+ * memory consistency. That is, for a given ValidationInterface()
+ * instantiation, each callback will complete before the next one is
+ * invoked. This means, for example when a block is connected that the
+ * UpdatedBlockTip() callback may depend on an operation performed in
+ * the BlockConnected() callback without worrying about explicit
+ * synchronization. No ordering should be assumed across
+ * ValidationInterface() subscribers.
+ */
class CValidationInterface {
protected:
/**
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 3ec6aefaec..218684fdf1 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -304,20 +304,18 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
}
}
-bool CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta)
+void CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
UpdateTimeFirstKey(meta.nCreateTime);
mapKeyMetadata[keyID] = meta;
- return true;
}
-bool CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta)
+void CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // m_script_metadata
UpdateTimeFirstKey(meta.nCreateTime);
m_script_metadata[script_id] = meta;
- return true;
}
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
@@ -470,11 +468,11 @@ void CWallet::ChainStateFlushed(const CBlockLocator& loc)
batch.WriteBestBlock(loc);
}
-bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
+void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
{
LOCK(cs_wallet); // nWalletVersion
if (nWalletVersion >= nVersion)
- return true;
+ return;
// when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
if (fExplicit && nVersion > nWalletMaxVersion)
@@ -492,8 +490,6 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in,
if (!batch_in)
delete batch;
}
-
- return true;
}
bool CWallet::SetMaxVersion(int nVersion)
@@ -703,9 +699,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// if we are using HD, replace the HD seed with a new one
if (IsHDEnabled()) {
- if (!SetHDSeed(GenerateNewSeed())) {
- return false;
- }
+ SetHDSeed(GenerateNewSeed());
}
NewKeyPool();
@@ -1006,7 +1000,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
return true;
}
-bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
+void CWallet::LoadToWallet(const CWalletTx& wtxIn)
{
uint256 hash = wtxIn.GetHash();
const auto& ins = mapWallet.emplace(hash, wtxIn);
@@ -1025,8 +1019,6 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
}
}
}
-
- return true;
}
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate)
@@ -1478,7 +1470,7 @@ CPubKey CWallet::DeriveNewSeed(const CKey& key)
return seed;
}
-bool CWallet::SetHDSeed(const CPubKey& seed)
+void CWallet::SetHDSeed(const CPubKey& seed)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
@@ -1488,18 +1480,15 @@ bool CWallet::SetHDSeed(const CPubKey& seed)
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
-
- return true;
}
-bool CWallet::SetHDChain(const CHDChain& chain, bool memonly)
+void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
{
LOCK(cs_wallet);
if (!memonly && !WalletBatch(*database).WriteHDChain(chain))
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
hdChain = chain;
- return true;
}
bool CWallet::IsHDEnabled() const
@@ -3029,7 +3018,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
std::string errString;
- if (!mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
+ LOCK(::mempool.cs);
+ if (!::mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
strFailReason = _("Transaction has too long of a mempool chain");
return false;
}
@@ -3899,10 +3889,9 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
return WalletBatch(*database).EraseDestData(EncodeDestination(dest), key);
}
-bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
+void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
{
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
- return true;
}
bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
@@ -4091,9 +4080,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// generate a new master key
CPubKey masterPubKey = walletInstance->GenerateNewSeed();
- if (!walletInstance->SetHDSeed(masterPubKey)) {
- throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
- }
+ walletInstance->SetHDSeed(masterPubKey);
hd_upgrade = true;
}
// Upgrade to HD chain split if necessary
@@ -4109,7 +4096,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
// Regenerate the keypool if upgraded to HD
if (hd_upgrade) {
if (!walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate keys") += "\n");
+ InitError(_("Unable to generate keys"));
return nullptr;
}
}
@@ -4130,14 +4117,12 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
} else {
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
- if (!walletInstance->SetHDSeed(seed)) {
- throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
- }
+ walletInstance->SetHDSeed(seed);
}
// Top up the keypool
if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !walletInstance->TopUpKeyPool()) {
- InitError(_("Unable to generate initial keys") += "\n");
+ InitError(_("Unable to generate initial keys"));
return nullptr;
}
@@ -4439,7 +4424,10 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
size_t ancestors, descendants;
mempool.GetTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
- if (gmap.count(dst) == 10) {
+ // Limit output groups to no more than 10 entries, to protect
+ // against inadvertently creating a too-large transaction
+ // when using -avoidpartialspends
+ if (gmap[dst].m_outputs.size() >= 10) {
groups.push_back(gmap[dst]);
gmap.erase(dst);
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 2ada233514..9f9501cf72 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -885,8 +885,8 @@ public:
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
//! Load metadata (used by LoadWallet)
- bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -903,7 +903,7 @@ public:
//! Erases a destination data tuple in the store and on disk
bool EraseDestData(const CTxDestination &dest, const std::string &key);
//! Adds a destination data tuple to the store, without saving it to disk
- bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+ void LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
//! Look up a destination data tuple in the store, return true if found false otherwise
bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;
//! Get all destination values matching a prefix.
@@ -936,7 +936,7 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
- bool LoadToWallet(const CWalletTx& wtxIn);
+ void LoadToWallet(const CWalletTx& wtxIn);
void TransactionAddedToMempool(const CTransactionRef& tx) override;
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
@@ -1075,7 +1075,7 @@ public:
}
//! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
- bool SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false);
+ void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false);
//! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
bool SetMaxVersion(int nVersion);
@@ -1146,7 +1146,7 @@ public:
bool BackupWallet(const std::string& strDest);
/* Set the HD chain model (chain child index counters) */
- bool SetHDChain(const CHDChain& chain, bool memonly);
+ void SetHDChain(const CHDChain& chain, bool memonly);
const CHDChain& GetHDChain() const { return hdChain; }
/* Returns true if HD is enabled */
@@ -1162,7 +1162,7 @@ public:
Sets the seed's version based on the current wallet version (so the
caller must ensure the current wallet version is correct before calling
this function). */
- bool SetHDSeed(const CPubKey& key);
+ void SetHDSeed(const CPubKey& key);
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 67fcaa725b..43e4747317 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -495,21 +495,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> strAddress;
ssKey >> strKey;
ssValue >> strValue;
- if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
- {
- strErr = "Error reading wallet database: LoadDestData failed";
- return false;
- }
+ pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue);
}
else if (strType == "hdchain")
{
CHDChain chain;
ssValue >> chain;
- if (!pwallet->SetHDChain(chain, true))
- {
- strErr = "Error reading wallet database: SetHDChain failed";
- return false;
- }
+ pwallet->SetHDChain(chain, true);
} else if (strType == "flags") {
uint64_t flags;
ssValue >> flags;