diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-05-24 10:24:17 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-05-24 10:31:36 +0200 |
commit | 50b2c9e0dfbe56766838e5b493e661b94b6a5cc7 (patch) | |
tree | 5b251be8a7681f2a3e067e3ea2d57840155fdfd7 | |
parent | 5d8de762579424d32c437bc3a7695d25e482c200 (diff) | |
parent | acdf4338221e35d5ec7b299bb18ccd953e28c985 (diff) |
Merge #13253: [0.16] Further Backports
acdf4338221e35d5ec7b299bb18ccd953e28c985 Hold cs_main while calling UpdatedBlockTip() and ui.NotifyBlockTip (Jesse Cohen)
5ff571e90c9fa71e189863e9cb21d15d5991f7da [wallet] [tests] Test disallowed multiwallet params (John Newbery)
4c14e7b67cd411b501e4a77385389da0afc9dd16 [wallet] Fix zapwallettxes/multiwallet interaction. (John Newbery)
4087dd08e7df5beedc335f4518b64eeab6a382c1 RPC Docs: gettxout*: clarify bestblock and unspent counts (David A. Harding)
b8aacd660eb9460b6a86d4402d886f0bb32af2b4 [qa] Handle disconnect_node race (Suhas Daftuar)
Pull request description:
Backports:
- #13201 [qa] Handle disconnect_node race
- #13184 RPC Docs: gettxout*: clarify bestblock and unspent counts
- #13030 [bugfix] [wallet] Fix zapwallettxes/multiwallet interaction.
- #12988 Hold cs_main while calling UpdatedBlockTip() signal
to the 0.16 branch.
Tree-SHA512: 8f65002bbafaf9c436f89051b2d79bf6a668fbd07bd317c64af238ed4a7c8efe776864b739a7f2869f1e3daa16f2f4366a85f41b188f9c454879d2c7b309be50
-rw-r--r-- | src/rpc/blockchain.cpp | 8 | ||||
-rw-r--r-- | src/validation.cpp | 19 | ||||
-rw-r--r-- | src/validationinterface.cpp | 4 | ||||
-rw-r--r-- | src/wallet/init.cpp | 10 | ||||
-rw-r--r-- | test/functional/test_framework/util.py | 9 | ||||
-rwxr-xr-x | test/functional/wallet_multiwallet.py | 13 |
6 files changed, 43 insertions, 20 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 346672e45a..14d0541cd7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -934,9 +934,9 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) "\nResult:\n" "{\n" " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" + " \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n" + " \"transactions\": n, (numeric) The number of transactions with unspent outputs\n" + " \"txouts\": n, (numeric) The number of unspent transaction outputs\n" " \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n" " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n" " \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n" @@ -979,7 +979,7 @@ UniValue gettxout(const JSONRPCRequest& request) " Note that an unspent output that is spent in the mempool won't appear.\n" "\nResult:\n" "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" + " \"bestblock\": \"hash\", (string) The hash of the block at the tip of the chain\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" " \"scriptPubKey\" : { (json object)\n" diff --git a/src/validation.cpp b/src/validation.cpp index 1f0ceba70c..f981d2659a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -351,7 +351,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool CBlockIndex* tip = chainActive.Tip(); assert(tip != nullptr); - + CBlockIndex index; index.pprev = tip; // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate @@ -2607,18 +2607,17 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& assert(trace.pblock && trace.pindex); GetMainSignals().BlockConnected(trace.pblock, trace.pindex, trace.conflictedTxs); } - } - // When we reach this point, we switched to a new tip (stored in pindexNewTip). - // Notifications/callbacks that can run without cs_main + // Notify external listeners about the new tip. + // Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected + GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); - // Notify external listeners about the new tip. - GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); - - // Always notify the UI if a new block tip was connected - if (pindexFork != pindexNewTip) { - uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); + // Always notify the UI if a new block tip was connected + if (pindexFork != pindexNewTip) { + uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); + } } + // When we reach this point, we switched to a new tip (stored in pindexNewTip). if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 928df4fa65..746263f113 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -139,6 +139,10 @@ void CMainSignals::MempoolEntryRemoved(CTransactionRef ptx, MemPoolRemovalReason } void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { + // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which + // the chain actually updates. One way to ensure this is for the caller to invoke this signal + // in the same critical section where the chain is updated + m_internals->m_schedulerClient.AddToProcessQueue([pindexNew, pindexFork, fInitialDownload, this] { m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); }); diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index ace95204b8..6e0b11cd9a 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -82,19 +82,19 @@ bool WalletParameterInteraction() } } - int zapwallettxes = gArgs.GetArg("-zapwallettxes", 0); + bool zapwallettxes = gArgs.GetBoolArg("-zapwallettxes", false); // -zapwallettxes implies dropping the mempool on startup - if (zapwallettxes != 0 && gArgs.SoftSetBoolArg("-persistmempool", false)) { - LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -persistmempool=0\n", __func__, zapwallettxes); + if (zapwallettxes && gArgs.SoftSetBoolArg("-persistmempool", false)) { + LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> setting -persistmempool=0\n", __func__); } // -zapwallettxes implies a rescan - if (zapwallettxes != 0) { + if (zapwallettxes) { if (is_multiwallet) { return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); } if (gArgs.SoftSetBoolArg("-rescan", true)) { - LogPrintf("%s: parameter interaction: -zapwallettxes=%s -> setting -rescan=1\n", __func__, zapwallettxes); + LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> setting -rescan=1\n", __func__); } } diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index ead1f844f7..8251da5f2f 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -335,7 +335,14 @@ def set_node_times(nodes, t): def disconnect_nodes(from_connection, node_num): for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: - from_connection.disconnectnode(nodeid=peer_id) + try: + from_connection.disconnectnode(nodeid=peer_id) + except JSONRPCException as e: + # If this node is disconnected between calculating the peer id + # and issuing the disconnect, don't worry about it. + # This avoids a race condition if we're mass-disconnecting peers. + if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED + raise # wait to disconnect wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == [], timeout=5) diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index b07e451667..3a34c43b7e 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -56,6 +56,19 @@ class MultiWalletTest(BitcoinTestFramework): open(not_a_dir, 'a').close() self.assert_start_raises_init_error(0, ['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + self.log.info("Do not allow -zapwallettxes with multiwallet") + self.assert_start_raises_init_error(0, ['-zapwallettxes', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + self.assert_start_raises_init_error(0, ['-zapwallettxes=1', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + self.assert_start_raises_init_error(0, ['-zapwallettxes=2', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + + self.log.info("Do not allow -salvagewallet with multiwallet") + self.assert_start_raises_init_error(0, ['-salvagewallet', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") + self.assert_start_raises_init_error(0, ['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") + + self.log.info("Do not allow -upgradewallet with multiwallet") + self.assert_start_raises_init_error(0, ['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") + self.assert_start_raises_init_error(0, ['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") + # if wallets/ doesn't exist, datadir should be the default wallet dir wallet_dir2 = data_dir('walletdir') os.rename(wallet_dir(), wallet_dir2) |