aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md35
-rw-r--r--src/wallet/rpcdump.cpp27
-rw-r--r--src/wallet/rpcwallet.cpp2
-rw-r--r--src/wallet/wallet.cpp9
-rw-r--r--src/wallet/wallet.h11
-rwxr-xr-xtest/functional/test_runner.py38
6 files changed, 112 insertions, 10 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0766d89f55..f5d63517b1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -37,8 +37,8 @@ fixes or code moves with actual code changes.
Commit messages should be verbose by default consisting of a short subject line
(50 chars max), a blank line and detailed explanatory text as separate
-paragraph(s); unless the title alone is self-explanatory (like "Corrected typo
-in init.cpp") then a single title line is sufficient. Commit messages should be
+paragraph(s), unless the title alone is self-explanatory (like "Corrected typo
+in init.cpp") in which case a single title line is sufficient. Commit messages should be
helpful to people reading your code in the future, so explain the reasoning for
your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/).
@@ -225,6 +225,37 @@ discussed extensively on the mailing list and IRC, be accompanied by a widely
discussed BIP and have a generally widely perceived technical consensus of being
a worthwhile change based on the judgement of the maintainers.
+### Finding Reviewers
+
+As most reviewers are themselves developers with their own projects, the review
+process can be quite lengthy, and some amount of patience is required. If you find
+that you've been waiting for a pull request to be given attention for several
+months, there may be a number of reasons for this, some of which you can do something
+about:
+
+ - It may be because of a feature freeze due to an upcoming release. During this time,
+ only bug fixes are taken into consideration. If your pull request is a new feature,
+ it will not be prioritized until the release is over. Wait for release.
+ - It may be because the changes you are suggesting do not appeal to people. Rather than
+ nits and critique, which require effort and means they care enough to spend time on your
+ contribution, thundering silence is a good sign of widespread (mild) dislike of a given change
+ (because people don't assume *others* won't actually like the proposal). Don't take
+ that personally, though! Instead, take another critical look at what you are suggesting
+ and see if it: changes too much, is too broad, doesn't adhere to the
+ [developer notes](doc/developer-notes.md), is dangerous or insecure, is messily written, etc.
+ Identify and address any of the issues you find. Then ask e.g. on IRC if someone could give
+ their opinion on the concept itself.
+ - It may be because your code is too complex for all but a few people. And those people
+ may not have realized your pull request even exists. A great way to find people who
+ are qualified and care about the code you are touching is the
+ [Git Blame feature](https://help.github.com/articles/tracing-changes-in-a-file/). Simply
+ find the person touching the code you are touching before you and see if you can find
+ them and give them a nudge. Don't be incessant about the nudging though.
+ - Finally, if all else fails, ask on IRC or elsewhere for someone to give your pull request
+ a look. If you think you've been waiting an unreasonably long amount of time (month+) for
+ no particular reason (few lines changed, etc), this is totally fine. Try to return the favor
+ when someone else is asking for feedback on their code, and universe balances out.
+
Release Policy
--------------
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 7ff9e7ae58..82708dab26 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -95,6 +95,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
+ HelpExampleCli("importprivkey", "\"mykey\"") +
"\nImport using a label and without rescan\n"
+ HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") +
+ "\nImport using default blank label and without rescan\n"
+ + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
);
@@ -154,6 +156,31 @@ UniValue importprivkey(const JSONRPCRequest& request)
return NullUniValue;
}
+UniValue abortrescan(const JSONRPCRequest& request)
+{
+ CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
+ if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ return NullUniValue;
+ }
+
+ if (request.fHelp || request.params.size() > 0)
+ throw std::runtime_error(
+ "abortrescan\n"
+ "\nStops current wallet rescan triggered e.g. by an importprivkey call.\n"
+ "\nExamples:\n"
+ "\nImport a private key\n"
+ + HelpExampleCli("importprivkey", "\"mykey\"") +
+ "\nAbort the running wallet rescan\n"
+ + HelpExampleCli("abortrescan", "") +
+ "\nAs a JSON-RPC call\n"
+ + HelpExampleRpc("abortrescan", "")
+ );
+
+ if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
+ pwallet->AbortRescan();
+ return true;
+}
+
void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel);
void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
{
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 2cc3072c16..665d856df5 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2914,6 +2914,7 @@ UniValue bumpfee(const JSONRPCRequest& request)
return result;
}
+extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue importprivkey(const JSONRPCRequest& request);
extern UniValue importaddress(const JSONRPCRequest& request);
@@ -2930,6 +2931,7 @@ static const CRPCCommand commands[] =
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} },
{ "hidden", "resendwallettransactions", &resendwallettransactions, true, {} },
{ "wallet", "abandontransaction", &abandontransaction, false, {"txid"} },
+ { "wallet", "abortrescan", &abortrescan, false, {} },
{ "wallet", "addmultisigaddress", &addmultisigaddress, true, {"nrequired","keys","account"} },
{ "wallet", "addwitnessaddress", &addwitnessaddress, true, {"address"} },
{ "wallet", "backupwallet", &backupwallet, true, {"destination"} },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index e9e18603b3..057d18f27d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1554,6 +1554,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
CBlockIndex* pindex = pindexStart;
{
LOCK2(cs_main, cs_wallet);
+ fAbortRescan = false;
+ fScanningWallet = true;
// no need to read and scan block, if block was created before
// our wallet birthday (as adjusted for block time variability)
@@ -1563,7 +1565,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
double dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex);
double dProgressTip = GuessVerificationProgress(chainParams.TxData(), chainActive.Tip());
- while (pindex)
+ while (pindex && !fAbortRescan)
{
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
@@ -1585,7 +1587,12 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
}
}
+ if (pindex && fAbortRescan) {
+ LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
+ }
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
+
+ fScanningWallet = false;
}
return ret;
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 2eb6bd9504..b3483f8308 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -651,6 +651,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
{
private:
static std::atomic<bool> fFlushScheduled;
+ std::atomic<bool> fAbortRescan;
+ std::atomic<bool> fScanningWallet;
/**
* Select a set of coins such that nValueRet >= nTargetValue and at least
@@ -779,6 +781,8 @@ public:
nTimeFirstKey = 0;
fBroadcastTransactions = false;
nRelockTime = 0;
+ fAbortRescan = false;
+ fScanningWallet = false;
}
std::map<uint256, CWalletTx> mapWallet;
@@ -823,6 +827,13 @@ public:
void UnlockAllCoins();
void ListLockedCoins(std::vector<COutPoint>& vOutpts);
+ /*
+ * Rescan abort properties
+ */
+ void AbortRescan() { fAbortRescan = true; }
+ bool IsAbortingRescan() { return fAbortRescan; }
+ bool IsScanning() { return fScanningWallet; }
+
/**
* keystore implementation
* Generate a new key
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 32ef199600..3a3fa31ec3 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -27,9 +27,17 @@ import logging
# Formatting. Default colors to empty strings.
BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
-TICK = "✓ "
-CROSS = "✖ "
-CIRCLE = "○ "
+try:
+ # Make sure python thinks it can write unicode to its stdout
+ "\u2713".encode("utf_8").decode(sys.stdout.encoding)
+ TICK = "✓ "
+ CROSS = "✖ "
+ CIRCLE = "○ "
+except UnicodeDecodeError:
+ TICK = "P "
+ CROSS = "x "
+ CIRCLE = "o "
+
if os.name == 'posix':
# primitive formatting on supported
# terminal via ANSI escape sequences:
@@ -164,6 +172,7 @@ def main():
parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).')
parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit')
parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.')
+ parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.')
parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs')
parser.add_argument('--nozmq', action='store_true', help='do not run the zmq tests')
args, unknown_args = parser.parse_known_args()
@@ -241,9 +250,23 @@ def main():
check_script_list(config["environment"]["SRCDIR"])
+ if not args.keepcache:
+ shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True)
+
run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args)
def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]):
+ # Warn if bitcoind is already running (unix only)
+ try:
+ if subprocess.check_output(["pidof", "bitcoind"]) is not None:
+ print("%sWARNING!%s There is already a bitcoind process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0]))
+ except (OSError, subprocess.SubprocessError):
+ pass
+
+ # Warn if there is a cache directory
+ cache_dir = "%s/test/cache" % build_dir
+ if os.path.isdir(cache_dir):
+ print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir))
#Set env vars
if "BITCOIND" not in os.environ:
@@ -252,7 +275,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal
tests_dir = src_dir + '/test/functional/'
flags = ["--srcdir={}/src".format(build_dir)] + args
- flags.append("--cachedir=%s/test/cache" % build_dir)
+ flags.append("--cachedir=%s" % cache_dir)
if enable_coverage:
coverage = RPCCoverage()
@@ -407,9 +430,10 @@ def check_script_list(src_dir):
python_files = set([t for t in os.listdir(script_dir) if t[-3:] == ".py"])
missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS)))
if len(missed_tests) != 0:
- print("The following scripts are not being run:" + str(missed_tests))
- print("Check the test lists in test_runner.py")
- sys.exit(1)
+ print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests)))
+ if os.getenv('TRAVIS') == 'true':
+ # On travis this warning is an error to prevent merging incomplete commits into master
+ sys.exit(1)
class RPCCoverage(object):
"""