aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/gitian-keys/keys.txt1
-rw-r--r--src/addrman.h2
-rw-r--r--src/bitcoin-cli.cpp3
-rw-r--r--src/core_read.cpp6
-rw-r--r--src/httpserver.cpp44
-rw-r--r--src/init.cpp19
-rw-r--r--src/net.cpp14
-rw-r--r--src/net_processing.cpp2
-rw-r--r--src/netaddress.cpp6
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/primitives/block.h4
-rw-r--r--src/protocol.h4
-rw-r--r--src/qt/bitcoin.cpp9
-rw-r--r--src/qt/bitcoingui.cpp6
-rw-r--r--src/qt/coincontroldialog.cpp6
-rw-r--r--src/qt/coincontroltreewidget.cpp2
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/walletmodel.cpp2
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/rpc/protocol.cpp4
-rw-r--r--src/script/ismine.cpp13
-rw-r--r--src/script/script.h2
-rw-r--r--src/test/versionbits_tests.cpp4
-rw-r--r--src/torcontrol.cpp6
-rw-r--r--src/txdb.h2
-rw-r--r--src/util.cpp22
-rw-r--r--src/util.h10
-rw-r--r--src/validation.cpp26
-rw-r--r--src/wallet/rpcdump.cpp29
-rw-r--r--src/wallet/wallet.h2
-rw-r--r--test/README.md4
-rwxr-xr-xtest/functional/wallet_dump.py20
34 files changed, 151 insertions, 133 deletions
diff --git a/contrib/gitian-keys/keys.txt b/contrib/gitian-keys/keys.txt
index 826902155e..47da725b74 100644
--- a/contrib/gitian-keys/keys.txt
+++ b/contrib/gitian-keys/keys.txt
@@ -1,3 +1,4 @@
+617C90010B3BD370B0AC7D424BB42E31C79111B8 Akira Takizawa
152812300785C96444D3334D17565732E08E5E41 Andrew Chow
E944AE667CF960B1004BC32FCA662BE18B877A60 Andreas Schildbach
07DF3E57A548CCFB7530709189BBB8663E2E65CE Matt Corallo (BlueMatt)
diff --git a/src/addrman.h b/src/addrman.h
index 172cb5f45b..38da754afb 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -59,7 +59,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*(CAddress*)this);
+ READWRITE(*static_cast<CAddress*>(this));
READWRITE(source);
READWRITE(nLastSuccess);
READWRITE(nAttempts);
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 1214b548cf..a60d3b3b6d 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -35,7 +35,7 @@ std::string HelpMessageCli()
std::string strUsage;
strUsage += HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("This help message"));
- strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
+ strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"), BITCOIN_CONF_FILENAME));
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
strUsage += HelpMessageOpt("-getinfo", _("Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)"));
AppendParamsHelpMessages(strUsage);
@@ -198,6 +198,7 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx)
class BaseRequestHandler
{
public:
+ virtual ~BaseRequestHandler() {}
virtual UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) = 0;
virtual UniValue ProcessReply(const UniValue &batch_in) = 0;
};
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 4ccb967087..6a8308f869 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -33,14 +33,14 @@ CScript ParseScript(const std::string& s)
if (op < OP_NOP && op != OP_RESERVED)
continue;
- const char* name = GetOpName((opcodetype)op);
+ const char* name = GetOpName(static_cast<opcodetype>(op));
if (strcmp(name, "OP_UNKNOWN") == 0)
continue;
std::string strName(name);
- mapOpNames[strName] = (opcodetype)op;
+ mapOpNames[strName] = static_cast<opcodetype>(op);
// Convenience: OP_ADD and just ADD are both recognized:
boost::algorithm::replace_first(strName, "OP_", "");
- mapOpNames[strName] = (opcodetype)op;
+ mapOpNames[strName] = static_cast<opcodetype>(op);
}
}
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index a022d220e0..36db530c82 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -73,34 +73,13 @@ private:
std::deque<std::unique_ptr<WorkItem>> queue;
bool running;
size_t maxDepth;
- int numThreads;
-
- /** RAII object to keep track of number of running worker threads */
- class ThreadCounter
- {
- public:
- WorkQueue &wq;
- explicit ThreadCounter(WorkQueue &w): wq(w)
- {
- std::lock_guard<std::mutex> lock(wq.cs);
- wq.numThreads += 1;
- }
- ~ThreadCounter()
- {
- std::lock_guard<std::mutex> lock(wq.cs);
- wq.numThreads -= 1;
- wq.cond.notify_all();
- }
- };
public:
explicit WorkQueue(size_t _maxDepth) : running(true),
- maxDepth(_maxDepth),
- numThreads(0)
+ maxDepth(_maxDepth)
{
}
- /** Precondition: worker threads have all stopped
- * (call WaitExit)
+ /** Precondition: worker threads have all stopped (they have been joined).
*/
~WorkQueue()
{
@@ -119,7 +98,6 @@ public:
/** Thread function */
void Run()
{
- ThreadCounter count(*this);
while (true) {
std::unique_ptr<WorkItem> i;
{
@@ -141,13 +119,6 @@ public:
running = false;
cond.notify_all();
}
- /** Wait for worker threads to exit */
- void WaitExit()
- {
- std::unique_lock<std::mutex> lock(cs);
- while (numThreads > 0)
- cond.wait(lock);
- }
};
struct HTTPPathHandler
@@ -449,6 +420,7 @@ bool UpdateHTTPServerLogging(bool enable) {
std::thread threadHTTP;
std::future<bool> threadResult;
+static std::vector<std::thread> g_thread_http_workers;
bool StartHTTPServer()
{
@@ -460,8 +432,7 @@ bool StartHTTPServer()
threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
for (int i = 0; i < rpcThreads; i++) {
- std::thread rpc_worker(HTTPWorkQueueRun, workQueue);
- rpc_worker.detach();
+ g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
}
return true;
}
@@ -486,7 +457,10 @@ void StopHTTPServer()
LogPrint(BCLog::HTTP, "Stopping HTTP server\n");
if (workQueue) {
LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
- workQueue->WaitExit();
+ for (auto& thread: g_thread_http_workers) {
+ thread.join();
+ }
+ g_thread_http_workers.clear();
delete workQueue;
workQueue = nullptr;
}
@@ -525,7 +499,7 @@ struct event_base* EventBase()
static void httpevent_callback_fn(evutil_socket_t, short, void* data)
{
// Static handler: simply call inner handler
- HTTPEvent *self = ((HTTPEvent*)data);
+ HTTPEvent *self = static_cast<HTTPEvent*>(data);
self->handler();
if (self->deleteWhenTriggered)
delete self;
diff --git a/src/init.cpp b/src/init.cpp
index 5e81e05f49..14dd8fc8ac 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -336,7 +336,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
if (showDebug)
strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY));
- strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
+ strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"), BITCOIN_CONF_FILENAME));
if (mode == HMM_BITCOIND)
{
#if HAVE_DECL_DAEMON
@@ -348,7 +348,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize));
}
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
- strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE));
+ strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf(_("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)"), DEFAULT_DEBUGLOGFILE));
if (showDebug)
strUsage += HelpMessageOpt("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER));
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
@@ -362,7 +362,7 @@ std::string HelpMessage(HelpMessageMode mode)
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL));
#ifndef WIN32
- strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME));
+ strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)"), BITCOIN_PID_FILENAME));
#endif
strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
@@ -500,7 +500,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"));
strUsage += HelpMessageOpt("-rpcauth=<userpw>", _("Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times"));
strUsage += HelpMessageOpt("-rpcbind=<addr>[:port]", _("Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)"));
- strUsage += HelpMessageOpt("-rpccookiefile=<loc>", _("Location of the auth cookie (default: data dir)"));
+ strUsage += HelpMessageOpt("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION));
@@ -1645,12 +1645,19 @@ bool AppInitMain()
// Wait for genesis block to be processed
{
WaitableLock lock(cs_GenesisWait);
- while (!fHaveGenesis) {
- condvar_GenesisWait.wait(lock);
+ // We previously could hang here if StartShutdown() is called prior to
+ // ThreadImport getting started, so instead we just wait on a timer to
+ // check ShutdownRequested() regularly.
+ while (!fHaveGenesis && !ShutdownRequested()) {
+ condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500));
}
uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
}
+ if (ShutdownRequested()) {
+ return false;
+ }
+
// ********************************************************* Step 11: start node
int chain_active_height;
diff --git a/src/net.cpp b/src/net.cpp
index b5d0b7de95..03ed7e7fc1 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -297,7 +297,7 @@ CNode* CConnman::FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if ((CNetAddr)pnode->addr == ip) {
+ if (static_cast<CNetAddr>(pnode->addr) == ip) {
return pnode;
}
}
@@ -308,7 +308,7 @@ CNode* CConnman::FindNode(const CSubNet& subNet)
{
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if (subNet.Match((CNetAddr)pnode->addr)) {
+ if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
return pnode;
}
}
@@ -330,7 +330,7 @@ CNode* CConnman::FindNode(const CService& addr)
{
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if ((CService)pnode->addr == addr) {
+ if (static_cast<CService>(pnode->addr) == addr) {
return pnode;
}
}
@@ -370,7 +370,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return nullptr;
// Look for an existing connection
- CNode* pnode = FindNode((CService)addrConnect);
+ CNode* pnode = FindNode(static_cast<CService>(addrConnect));
if (pnode)
{
LogPrintf("Failed to open new connection, already connected\n");
@@ -398,7 +398,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
// Also store the name we used to connect in that CNode, so that future FindNode() calls to that
// name catch this early.
LOCK(cs_vNodes);
- CNode* pnode = FindNode((CService)addrConnect);
+ CNode* pnode = FindNode(static_cast<CService>(addrConnect));
if (pnode)
{
pnode->MaybeSetAddrName(std::string(pszDest));
@@ -559,7 +559,7 @@ void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t ba
{
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if (subNet.Match((CNetAddr)pnode->addr))
+ if (subNet.Match(static_cast<CNetAddr>(pnode->addr)))
pnode->fDisconnect = true;
}
}
@@ -1965,7 +1965,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
}
if (!pszDest) {
if (IsLocal(addrConnect) ||
- FindNode((CNetAddr)addrConnect) || IsBanned(addrConnect) ||
+ FindNode(static_cast<CNetAddr>(addrConnect)) || IsBanned(addrConnect) ||
FindNode(addrConnect.ToStringIPPort()))
return;
} else if (FindNode(std::string(pszDest)))
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index edebccfb31..fc0ba82d8b 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2863,7 +2863,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman)
CNodeState &state = *State(pnode->GetId());
for (const CBlockReject& reject : state.rejects) {
- connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
}
state.rejects.clear();
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 81f72879f4..4f231d73c8 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -522,17 +522,17 @@ unsigned short CService::GetPort() const
bool operator==(const CService& a, const CService& b)
{
- return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
+ return static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port == b.port;
}
bool operator!=(const CService& a, const CService& b)
{
- return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
+ return static_cast<CNetAddr>(a) != static_cast<CNetAddr>(b) || a.port != b.port;
}
bool operator<(const CService& a, const CService& b)
{
- return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
+ return static_cast<CNetAddr>(a) < static_cast<CNetAddr>(b) || (static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port < b.port);
}
bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
diff --git a/src/netbase.cpp b/src/netbase.cpp
index d51277c495..5be3fe34f8 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -572,7 +572,7 @@ bool HaveNameProxy() {
bool IsProxy(const CNetAddr &addr) {
LOCK(cs_proxyInfos);
for (int i = 0; i < NET_MAX; i++) {
- if (addr == (CNetAddr)proxyInfo[i].proxy)
+ if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
return true;
}
return false;
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 612a9fa203..5d6d44ac76 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -86,14 +86,14 @@ public:
CBlock(const CBlockHeader &header)
{
SetNull();
- *((CBlockHeader*)this) = header;
+ *(static_cast<CBlockHeader*>(this)) = header;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*(CBlockHeader*)this);
+ READWRITE(*static_cast<CBlockHeader*>(this));
READWRITE(vtx);
}
diff --git a/src/protocol.h b/src/protocol.h
index aaeb90eee2..42eb57e4f0 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -346,8 +346,8 @@ public:
READWRITE(nTime);
uint64_t nServicesInt = nServices;
READWRITE(nServicesInt);
- nServices = (ServiceFlags)nServicesInt;
- READWRITE(*(CService*)this);
+ nServices = static_cast<ServiceFlags>(nServicesInt);
+ READWRITE(*static_cast<CService*>(this));
}
// TODO: make private (improves encapsulation)
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index b26d99a20a..e4c088d379 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -388,7 +388,6 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
pollShutdownTimer = new QTimer(window);
connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
- pollShutdownTimer->start(200);
}
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
@@ -515,14 +514,16 @@ void BitcoinApplication::initializeResult(bool success)
window, SLOT(message(QString,QString,unsigned int)));
QTimer::singleShot(100, paymentServer, SLOT(uiReady()));
#endif
+ pollShutdownTimer->start(200);
} else {
- quit(); // Exit main loop
+ Q_EMIT splashFinished(window); // Make sure splash screen doesn't stick around during shutdown
+ quit(); // Exit first main loop invocation
}
}
void BitcoinApplication::shutdownResult()
{
- quit(); // Exit main loop after shutdown finished
+ quit(); // Exit second main loop invocation after shutdown finished
}
void BitcoinApplication::handleRunawayException(const QString &message)
@@ -705,7 +706,7 @@ int main(int argc, char *argv[])
if (BitcoinCore::baseInitialize()) {
app.requestInitialize();
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
- WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId());
+ WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), static_cast<HWND>(app.getMainWinId()));
#endif
app.exec();
app.requestShutdown();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index afd90a3bc6..4e868b7c17 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -599,7 +599,7 @@ void BitcoinGUI::createTrayIconMenu()
#else
// Note: On Mac, the dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- dockIconHandler->setMainWindow((QMainWindow *)this);
+ dockIconHandler->setMainWindow(static_cast<QMainWindow*>(this));
trayIconMenu = dockIconHandler->dockMenu();
#endif
@@ -922,13 +922,13 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
buttons = QMessageBox::Ok;
showNormalIfMinimized();
- QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons, this);
+ QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle, message, buttons, this);
int r = mBox.exec();
if (ret != nullptr)
*ret = r == QMessageBox::Ok;
}
else
- notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
+ notificator->notify(static_cast<Notificator::Class>(nNotifyIcon), strTitle, message);
}
void BitcoinGUI::changeEvent(QEvent *e)
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index acb3f2346f..8d2e5619e0 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -142,7 +142,7 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
if (settings.contains("nCoinControlMode") && !settings.value("nCoinControlMode").toBool())
ui->radioTreeMode->click();
if (settings.contains("nCoinControlSortColumn") && settings.contains("nCoinControlSortOrder"))
- sortView(settings.value("nCoinControlSortColumn").toInt(), ((Qt::SortOrder)settings.value("nCoinControlSortOrder").toInt()));
+ sortView(settings.value("nCoinControlSortColumn").toInt(), (static_cast<Qt::SortOrder>(settings.value("nCoinControlSortOrder").toInt())));
}
CoinControlDialog::~CoinControlDialog()
@@ -428,7 +428,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if (amount > 0)
{
- CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
+ CTxOut txout(amount, static_cast<CScript>(std::vector<unsigned char>(24, 0)));
txDummy.vout.push_back(txout);
fDust |= IsDust(txout, ::dustRelayFee);
}
@@ -519,7 +519,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// Never create dust outputs; if we would, just add the dust to the fee.
if (nChange > 0 && nChange < MIN_CHANGE)
{
- CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
+ CTxOut txout(nChange, static_cast<CScript>(std::vector<unsigned char>(24, 0)));
if (IsDust(txout, ::dustRelayFee))
{
nPayFee += nChange;
diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp
index 82db28d586..e7326d3f7a 100644
--- a/src/qt/coincontroltreewidget.cpp
+++ b/src/qt/coincontroltreewidget.cpp
@@ -24,7 +24,7 @@ void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event)
else if (event->key() == Qt::Key_Escape) // press esc -> close dialog
{
event->ignore();
- CoinControlDialog *coinControlDialog = (CoinControlDialog*)this->parentWidget();
+ CoinControlDialog *coinControlDialog = static_cast<CoinControlDialog*>(this->parentWidget());
coinControlDialog->done(QDialog::Accepted);
}
else
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 1227e340ce..871822ccb4 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -351,7 +351,7 @@ void SendCoinsDialog::on_sendButton_clicked()
SendConfirmationDialog confirmationDialog(tr("Confirm send coins"),
questionString.arg(formatted.join("<br />")), SEND_CONFIRM_DELAY, this);
confirmationDialog.exec();
- QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
+ QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result());
if(retval != QMessageBox::Yes)
{
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index fa3bd18d5a..5df1282f73 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -38,7 +38,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
float fontFactor = 1.0;
float devicePixelRatio = 1.0;
#if QT_VERSION > 0x050100
- devicePixelRatio = ((QGuiApplication*)QCoreApplication::instance())->devicePixelRatio();
+ devicePixelRatio = static_cast<QGuiApplication*>(QCoreApplication::instance())->devicePixelRatio();
#endif
// define text to place
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index fa43ab750a..88f8f463bc 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -322,7 +322,7 @@ void TransactionView::chooseWatchonly(int idx)
if(!transactionProxyModel)
return;
transactionProxyModel->setWatchOnlyFilter(
- (TransactionFilterProxy::WatchOnlyFilter)watchOnlyWidget->itemData(idx).toInt());
+ static_cast<TransactionFilterProxy::WatchOnlyFilter>(watchOnlyWidget->itemData(idx).toInt()));
}
void TransactionView::changedSearch()
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 4d7e977fcb..541114e5fe 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -695,7 +695,7 @@ bool WalletModel::bumpFee(uint256 hash)
questionString.append("</td></tr></table>");
SendConfirmationDialog confirmationDialog(tr("Confirm fee bump"), questionString);
confirmationDialog.exec();
- QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
+ QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result());
// cancel sign&broadcast if users doesn't want to bump the fee
if (retval != QMessageBox::Yes) {
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 1e7a76efc0..e11a72899d 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -56,7 +56,7 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM
void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId)
{
typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR);
- PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate");
+ PSHUTDOWNBRCREATE shutdownBRCreate = static_cast<PSHUTDOWNBRCREATE>(GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate"));
if (shutdownBRCreate == nullptr) {
qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed";
return;
diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp
index ddc1bb6232..cdd2e67a69 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -72,9 +72,7 @@ static fs::path GetAuthCookieFile(bool temp=false)
if (temp) {
arg += ".tmp";
}
- fs::path path(arg);
- if (!path.is_complete()) path = GetDataDir() / path;
- return path;
+ return AbsPathForConfigVal(fs::path(arg));
}
bool GenerateAuthCookie(std::string *cookie_out)
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index d0dd272550..35d794b983 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -13,16 +13,13 @@
typedef std::vector<unsigned char> valtype;
-unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
+static bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
{
- unsigned int nResult = 0;
- for (const valtype& pubkey : pubkeys)
- {
+ for (const valtype& pubkey : pubkeys) {
CKeyID keyID = CPubKey(pubkey).GetID();
- if (keystore.HaveKey(keyID))
- ++nResult;
+ if (!keystore.HaveKey(keyID)) return false;
}
- return nResult;
+ return true;
}
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
@@ -140,7 +137,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
}
}
}
- if (HaveKeys(keys, keystore) == keys.size())
+ if (HaveKeys(keys, keystore))
return ISMINE_SPENDABLE;
break;
}
diff --git a/src/script/script.h b/src/script/script.h
index bedf5f9be5..591777672e 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -568,7 +568,7 @@ public:
pc += nSize;
}
- opcodeRet = (opcodetype)opcode;
+ opcodeRet = static_cast<opcodetype>(opcode);
return true;
}
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 12f113655a..5d6f781404 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
const Consensus::Params &mainnetParams = chainParams->GetConsensus();
for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
- uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i);
+ uint32_t bitmask = VersionBitsMask(mainnetParams, static_cast<Consensus::DeploymentPos>(i));
// Make sure that no deployment tries to set an invalid bit.
BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask);
@@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
// activated soft fork could be later changed to be earlier to avoid
// overlap.)
for (int j=i+1; j<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) {
- if (VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)j) == bitmask) {
+ if (VersionBitsMask(mainnetParams, static_cast<Consensus::DeploymentPos>(j)) == bitmask) {
BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > mainnetParams.vDeployments[i].nTimeout ||
mainnetParams.vDeployments[i].nStartTime > mainnetParams.vDeployments[j].nTimeout);
}
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index c45b5dac0d..d875008ef2 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -133,7 +133,7 @@ TorControlConnection::~TorControlConnection()
void TorControlConnection::readcb(struct bufferevent *bev, void *ctx)
{
- TorControlConnection *self = (TorControlConnection*)ctx;
+ TorControlConnection *self = static_cast<TorControlConnection*>(ctx);
struct evbuffer *input = bufferevent_get_input(bev);
size_t n_read_out = 0;
char *line;
@@ -178,7 +178,7 @@ void TorControlConnection::readcb(struct bufferevent *bev, void *ctx)
void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ctx)
{
- TorControlConnection *self = (TorControlConnection*)ctx;
+ TorControlConnection *self = static_cast<TorControlConnection*>(ctx);
if (what & BEV_EVENT_CONNECTED) {
LogPrint(BCLog::TOR, "tor: Successfully connected!\n");
self->connected(*self);
@@ -725,7 +725,7 @@ fs::path TorController::GetPrivateKeyFile()
void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg)
{
- TorController *self = (TorController*)arg;
+ TorController *self = static_cast<TorController*>(arg);
self->Reconnect();
}
diff --git a/src/txdb.h b/src/txdb.h
index 3edeb4648e..2fc69e563b 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -46,7 +46,7 @@ struct CDiskTxPos : public CDiskBlockPos
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*(CDiskBlockPos*)this);
+ READWRITE(*static_cast<CDiskBlockPos*>(this));
READWRITE(VARINT(nTxOffset));
}
diff --git a/src/util.cpp b/src/util.cpp
index 80eed24ffd..6738bbc6e4 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util.h>
+#include <fs.h>
#include <chainparamsbase.h>
#include <random.h>
@@ -188,11 +189,7 @@ static void DebugPrintInit()
fs::path GetDebugLogPath()
{
fs::path logfile(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
- if (logfile.is_absolute()) {
- return logfile;
- } else {
- return GetDataDir() / logfile;
- }
+ return AbsPathForConfigVal(logfile);
}
bool OpenDebugLog()
@@ -624,11 +621,7 @@ void ClearDatadirCache()
fs::path GetConfigFile(const std::string& confPath)
{
- fs::path pathConfigFile(confPath);
- if (!pathConfigFile.is_complete())
- pathConfigFile = GetDataDir(false) / pathConfigFile;
-
- return pathConfigFile;
+ return AbsPathForConfigVal(fs::path(confPath), false);
}
void ArgsManager::ReadConfigFile(const std::string& confPath)
@@ -663,9 +656,7 @@ void ArgsManager::ReadConfigFile(const std::string& confPath)
#ifndef WIN32
fs::path GetPidFile()
{
- fs::path pathPidFile(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME));
- if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
- return pathPidFile;
+ return AbsPathForConfigVal(fs::path(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME)));
}
void CreatePidFile(const fs::path &path, pid_t pid)
@@ -936,3 +927,8 @@ int64_t GetStartupTime()
{
return nStartupTime;
}
+
+fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
+{
+ return fs::absolute(path, GetDataDir(net_specific));
+}
diff --git a/src/util.h b/src/util.h
index 277b4c66af..05138a9bfe 100644
--- a/src/util.h
+++ b/src/util.h
@@ -191,6 +191,16 @@ bool OpenDebugLog();
void ShrinkDebugFile();
void runCommand(const std::string& strCommand);
+/**
+ * Most paths passed as configuration arguments are treated as relative to
+ * the datadir if they are not absolute.
+ *
+ * @param path The path to be conditionally prefixed with datadir.
+ * @param net_specific Forwarded to GetDataDir().
+ * @return The normalized path.
+ */
+fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific = true);
+
inline bool IsSwitchChar(char c)
{
#ifdef WIN32
diff --git a/src/validation.cpp b/src/validation.cpp
index 698ef9181d..978aaf7d06 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -547,8 +547,10 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
const CTransaction& tx = *ptx;
const uint256 hash = tx.GetHash();
AssertLockHeld(cs_main);
- if (pfMissingInputs)
+ LOCK(pool.cs); // mempool "read lock" (held through GetMainSignals().TransactionAddedToMempool())
+ if (pfMissingInputs) {
*pfMissingInputs = false;
+ }
if (!CheckTransaction(tx, state))
return false; // state filled in by CheckTransaction
@@ -581,8 +583,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Check for conflicts with in-memory transactions
std::set<uint256> setConflicts;
- {
- LOCK(pool.cs); // protect pool.mapNextTx
for (const CTxIn &txin : tx.vin)
{
auto itConflicting = pool.mapNextTx.find(txin.prevout);
@@ -623,15 +623,12 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
}
}
- }
{
CCoinsView dummy;
CCoinsViewCache view(&dummy);
LockPoints lp;
- {
- LOCK(pool.cs);
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool);
view.SetBackend(viewMemPool);
@@ -670,8 +667,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");
- } // end LOCK(pool.cs)
-
CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), nFees)) {
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
@@ -768,7 +763,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// If we don't hold the lock allConflicting might be incomplete; the
// subsequent RemoveStaged() and addUnchecked() calls don't guarantee
// mempool consistency for us.
- LOCK(pool.cs);
const bool fReplacementTransaction = setConflicts.size();
if (fReplacementTransaction)
{
@@ -1689,9 +1683,9 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
int32_t nVersion = VERSIONBITS_TOP_BITS;
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
- ThresholdState state = VersionBitsState(pindexPrev, params, (Consensus::DeploymentPos)i, versionbitscache);
+ ThresholdState state = VersionBitsState(pindexPrev, params, static_cast<Consensus::DeploymentPos>(i), versionbitscache);
if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
- nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i);
+ nVersion |= VersionBitsMask(params, static_cast<Consensus::DeploymentPos>(i));
}
}
@@ -2581,9 +2575,6 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
SyncWithValidationInterfaceQueue();
}
- if (ShutdownRequested())
- break;
-
const CBlockIndex *pindexFork;
bool fInitialDownload;
{
@@ -2630,6 +2621,13 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
}
if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
+
+ // We check shutdown only after giving ActivateBestChainStep a chance to run once so that we
+ // never shutdown before connecting the genesis block during LoadChainTip(). Previously this
+ // caused an assert() failure during shutdown in such cases as the UTXO DB flushing checks
+ // that the best block hash is non-null.
+ if (ShutdownRequested())
+ break;
} while (pindexNewTip != pindexMostWork);
CheckBlockIndex(chainparams.GetConsensus());
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 0b021f9fe0..03fb824e7a 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -71,6 +71,28 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
+bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
+{
+ bool fLabelFound = false;
+ CKey key;
+ pwallet->GetKey(keyid, key);
+ for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) {
+ if (pwallet->mapAddressBook.count(dest)) {
+ if (!strAddr.empty()) {
+ strAddr += ",";
+ }
+ strAddr += EncodeDestination(dest);
+ strLabel = EncodeDumpString(pwallet->mapAddressBook[dest].name);
+ fLabelFound = true;
+ }
+ }
+ if (!fLabelFound) {
+ strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), g_address_type));
+ }
+ return fLabelFound;
+}
+
+
UniValue importprivkey(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
@@ -729,12 +751,13 @@ UniValue dumpwallet(const JSONRPCRequest& request)
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
- std::string strAddr = EncodeDestination(keyid);
+ std::string strAddr;
+ std::string strLabel;
CKey key;
if (pwallet->GetKey(keyid, key)) {
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
- if (pwallet->mapAddressBook.count(keyid)) {
- file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook[keyid].name));
+ if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
+ file << strprintf("label=%s", strLabel);
} else if (keyid == masterKeyID) {
file << "hdmaster=1";
} else if (mapKeyPool.count(keyid)) {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a4684c2935..fefe415bb1 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -408,7 +408,7 @@ public:
mapValue["timesmart"] = strprintf("%u", nTimeSmart);
}
- READWRITE(*(CMerkleTx*)this);
+ READWRITE(*static_cast<CMerkleTx*>(this));
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
READWRITE(vUnused);
READWRITE(mapValue);
diff --git a/test/README.md b/test/README.md
index b59c8db4e5..b522c4469a 100644
--- a/test/README.md
+++ b/test/README.md
@@ -33,13 +33,13 @@ The ZMQ functional test requires a python ZMQ library. To install it:
Individual tests can be run by directly calling the test script, eg:
```
-test/functional/replace-by-fee.py
+test/functional/feature_rbf.py
```
or can be run through the test_runner harness, eg:
```
-test/functional/test_runner.py replace-by-fee.py
+test/functional/test_runner.py feature_rbf.py
```
You can run any combination (incl. duplicates) of tests by calling:
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 77f90ffb81..5e943d048d 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -20,6 +20,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr = 0
found_addr_chg = 0
found_addr_rsv = 0
+ witness_addr_ret = None
hd_master_addr_ret = None
for line in inputfile:
# only read non comment lines
@@ -47,7 +48,14 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
# count key types
for addrObj in addrs:
- if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=":
+ if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=":
+ # a labled entry in the wallet should contain both a native address
+ # and the p2sh-p2wpkh address that was added at wallet setup
+ if len(addr.split(",")) == 2:
+ addr_list = addr.split(",")
+ # the entry should be of the first key in the wallet
+ assert_equal(addrs[0]['address'], addr_list[0])
+ witness_addr_ret = addr_list[1]
found_addr += 1
break
elif keytype == "change=1":
@@ -63,7 +71,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr += 1
break
- return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
+ return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret
class WalletDumpTest(BitcoinTestFramework):
@@ -83,6 +91,8 @@ class WalletDumpTest(BitcoinTestFramework):
tmpdir = self.options.tmpdir
# generate 20 addresses to compare against the dump
+ # but since we add a p2sh-p2wpkh address for the first pubkey in the
+ # wallet, we will expect 21 addresses in the dump
test_addr_count = 20
addrs = []
for i in range(0,test_addr_count):
@@ -101,12 +111,13 @@ class WalletDumpTest(BitcoinTestFramework):
result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump")
assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump"))
- found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
+ found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc, witness_addr_ret = \
read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, script_addrs, None)
assert_equal(found_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_script_addr, 2) # all scripts must be in the dump
assert_equal(found_addr_chg, 50) # 50 blocks where mined
assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys
+ assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key
#encrypt wallet, restart, unlock and dump
self.nodes[0].node_encrypt_wallet('test')
@@ -116,12 +127,13 @@ class WalletDumpTest(BitcoinTestFramework):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump")
- found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
+ found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _, witness_addr_ret = \
read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, script_addrs, hd_master_addr_unenc)
assert_equal(found_addr, test_addr_count)
assert_equal(found_script_addr, 2)
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
assert_equal(found_addr_rsv, 90*2)
+ assert_equal(witness_addr_ret, witness_addr)
# Overwriting should fail
assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump")