aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2019-04-22 14:30:02 -0400
committerMarcoFalke <falke.marco@gmail.com>2019-05-06 14:03:56 -0400
commitfaf3729242c5e9486e137e549f05bf20bd3908a0 (patch)
tree2e8eac01221ff69a1c9c5ccacff731d6ee0ed1ff
parent3356799ee3f5441b8d6e68b9172eb641011354f8 (diff)
wallet: Only fail rescan when blocks have actually been pruned
-rw-r--r--src/interfaces/chain.cpp8
-rw-r--r--src/interfaces/chain.h6
-rw-r--r--src/wallet/rpcdump.cpp26
-rw-r--r--src/wallet/wallet.cpp11
-rwxr-xr-xtest/functional/wallet_import_rescan.py25
5 files changed, 42 insertions, 34 deletions
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index 839af650bb..1a60d4fd09 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -325,7 +325,11 @@ public:
CFeeRate relayMinFee() override { return ::minRelayTxFee; }
CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
CFeeRate relayDustFee() override { return ::dustRelayFee; }
- bool getPruneMode() override { return ::fPruneMode; }
+ bool havePruned() override
+ {
+ LOCK(cs_main);
+ return ::fHavePruned;
+ }
bool p2pEnabled() override { return g_connman != nullptr; }
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !IsInitialBlockDownload(); }
bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 7564ad26ac..550b2fe28e 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2018 The Bitcoin Core developers
+// Copyright (c) 2018-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -207,8 +207,8 @@ public:
//! Relay dust fee setting (-dustrelayfee), reflecting lowest rate it's economical to spend.
virtual CFeeRate relayDustFee() = 0;
- //! Check if pruning is enabled.
- virtual bool getPruneMode() = 0;
+ //! Check if any block has been pruned.
+ virtual bool havePruned() = 0;
//! Check if p2p enabled.
virtual bool p2pEnabled() = 0;
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index c339e111ba..214f4bf503 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -157,8 +157,11 @@ UniValue importprivkey(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && pwallet->chain().getPruneMode()) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && pwallet->chain().havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will import the key(s),
+ // but fail the rescan with a generic error.
+ throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled when blocks are pruned");
}
if (fRescan && !reserver.reserve()) {
@@ -314,8 +317,11 @@ UniValue importaddress(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && pwallet->chain().getPruneMode()) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && pwallet->chain().havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will import the key(s),
+ // but fail the rescan with a generic error.
+ throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled when blocks are pruned");
}
WalletRescanReserver reserver(pwallet);
@@ -507,8 +513,11 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (!request.params[2].isNull())
fRescan = request.params[2].get_bool();
- if (fRescan && pwallet->chain().getPruneMode()) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled in pruned mode");
+ if (fRescan && pwallet->chain().havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will import the key(s),
+ // but fail the rescan with a generic error.
+ throw JSONRPCError(RPC_WALLET_ERROR, "Rescan is disabled when blocks are pruned");
}
WalletRescanReserver reserver(pwallet);
@@ -573,7 +582,10 @@ UniValue importwallet(const JSONRPCRequest& request)
},
}.ToString());
- if (pwallet->chain().getPruneMode()) {
+ if (pwallet->chain().havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will import the key(s),
+ // but fail the rescan with a generic error.
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8bbb47c093..1b8dbdb65a 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -4219,10 +4219,13 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (tip_height && *tip_height != rescan_height)
{
- //We can't rescan beyond non-pruned blocks, stop and throw an error
- //this might happen if a user uses an old wallet within a pruned node
- // or if he ran -disablewallet for a longer time, then decided to re-enable
- if (chain.getPruneMode()) {
+ // We can't rescan beyond non-pruned blocks, stop and throw an error.
+ // This might happen if a user uses an old wallet within a pruned node
+ // or if they ran -disablewallet for a longer time, then decided to re-enable
+ if (chain.havePruned()) {
+ // Exit early and print an error.
+ // If a block is pruned after this check, we will load the wallet,
+ // but fail the rescan with a generic error.
int block_height = *tip_height;
while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
--block_height;
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 9de30d0374..47c97f62bf 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -21,7 +21,6 @@ happened previously.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- assert_raises_rpc_error,
connect_nodes,
assert_equal,
set_node_times,
@@ -39,23 +38,17 @@ Rescan = enum.Enum("Rescan", "no yes late_timestamp")
class Variant(collections.namedtuple("Variant", "call data rescan prune")):
"""Helper for importing one key and verifying scanned transactions."""
- def try_rpc(self, func, *args, **kwargs):
- if self.expect_disabled:
- assert_raises_rpc_error(-4, "Rescan is disabled in pruned mode", func, *args, **kwargs)
- else:
- return func(*args, **kwargs)
-
def do_import(self, timestamp):
"""Call one key import RPC."""
rescan = self.rescan == Rescan.yes
if self.call == Call.single:
if self.data == Data.address:
- response = self.try_rpc(self.node.importaddress, address=self.address["address"], label=self.label, rescan=rescan)
+ response = self.node.importaddress(address=self.address["address"], label=self.label, rescan=rescan)
elif self.data == Data.pub:
- response = self.try_rpc(self.node.importpubkey, pubkey=self.address["pubkey"], label=self.label, rescan=rescan)
+ response = self.node.importpubkey(pubkey=self.address["pubkey"], label=self.label, rescan=rescan)
elif self.data == Data.priv:
- response = self.try_rpc(self.node.importprivkey, privkey=self.key, label=self.label, rescan=rescan)
+ response = self.node.importprivkey(privkey=self.key, label=self.label, rescan=rescan)
assert_equal(response, None)
elif self.call in (Call.multiaddress, Call.multiscript):
@@ -172,8 +165,7 @@ class ImportRescanTest(BitcoinTestFramework):
# check the results from getbalance and listtransactions.
for variant in IMPORT_VARIANTS:
self.log.info('Run import for variant {}'.format(variant))
- variant.expect_disabled = variant.rescan == Rescan.yes and variant.prune and variant.call == Call.single
- expect_rescan = variant.rescan == Rescan.yes and not variant.expect_disabled
+ expect_rescan = variant.rescan == Rescan.yes
variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
variant.do_import(timestamp)
if expect_rescan:
@@ -198,12 +190,9 @@ class ImportRescanTest(BitcoinTestFramework):
# Check the latest results from getbalance and listtransactions.
for variant in IMPORT_VARIANTS:
self.log.info('Run check for variant {}'.format(variant))
- if not variant.expect_disabled:
- variant.expected_balance += variant.sent_amount
- variant.expected_txs += 1
- variant.check(variant.sent_txid, variant.sent_amount, 1)
- else:
- variant.check()
+ variant.expected_balance += variant.sent_amount
+ variant.expected_txs += 1
+ variant.check(variant.sent_txid, variant.sent_amount, 1)
if __name__ == "__main__":
ImportRescanTest().main()