aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--configure.ac2
-rwxr-xr-xcontrib/devtools/lint-logs.sh5
-rwxr-xr-xcontrib/tidy_datadir.sh62
-rw-r--r--doc/release-notes.md19
-rw-r--r--doc/tor.md18
-rw-r--r--share/rpcauth/README.md4
-rwxr-xr-xshare/rpcauth/rpcauth.py17
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bench/bench_bitcoin.cpp1
-rw-r--r--src/bench/prevector.cpp2
-rw-r--r--src/bitcoin-cli.cpp6
-rw-r--r--src/bitcoind.cpp4
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/core_read.cpp2
-rw-r--r--src/httpserver.cpp4
-rw-r--r--src/httpserver.h2
-rw-r--r--src/index/txindex.cpp8
-rw-r--r--src/index/txindex.h2
-rw-r--r--src/init.cpp64
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/keystore.h2
-rw-r--r--src/logging.cpp228
-rw-r--r--src/logging.h85
-rw-r--r--src/net.cpp6
-rw-r--r--src/net_processing.cpp33
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/policy/rbf.h2
-rw-r--r--src/qt/README.md2
-rw-r--r--src/qt/addresstablemodel.cpp2
-rw-r--r--src/qt/addresstablemodel.h6
-rw-r--r--src/qt/paymentserver.cpp2
-rw-r--r--src/qt/rpcconsole.cpp7
-rw-r--r--src/qt/rpcconsole.h18
-rw-r--r--src/random.cpp2
-rw-r--r--src/rest.cpp4
-rw-r--r--src/rpc/blockchain.cpp58
-rw-r--r--src/rpc/mining.cpp22
-rw-r--r--src/rpc/misc.cpp51
-rw-r--r--src/rpc/net.cpp24
-rw-r--r--src/rpc/protocol.h4
-rw-r--r--src/rpc/rawtransaction.cpp27
-rw-r--r--src/rpc/safemode.cpp14
-rw-r--r--src/rpc/safemode.h12
-rw-r--r--src/rpc/server.cpp2
-rw-r--r--src/script/ismine.cpp78
-rw-r--r--src/script/ismine.h7
-rw-r--r--src/script/standard.h2
-rw-r--r--src/support/lockedpool.cpp2
-rw-r--r--src/test/DoS_tests.cpp6
-rw-r--r--src/test/arith_uint256_tests.cpp10
-rw-r--r--src/test/bech32_tests.cpp2
-rw-r--r--src/test/bip32_tests.cpp2
-rw-r--r--src/test/blockchain_tests.cpp10
-rw-r--r--src/test/checkqueue_tests.cpp2
-rw-r--r--src/test/coins_tests.cpp12
-rw-r--r--src/test/crypto_tests.cpp26
-rw-r--r--src/test/cuckoocache_tests.cpp12
-rw-r--r--src/test/dbwrapper_tests.cpp2
-rw-r--r--src/test/main_tests.cpp4
-rw-r--r--src/test/mempool_tests.cpp2
-rw-r--r--src/test/miner_tests.cpp6
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/net_tests.cpp2
-rw-r--r--src/test/script_standard_tests.cpp9
-rw-r--r--src/test/script_tests.cpp8
-rw-r--r--src/test/sigopcount_tests.cpp4
-rw-r--r--src/test/test_bitcoin.cpp1
-rw-r--r--src/test/test_bitcoin_fuzzy.cpp4
-rw-r--r--src/test/torcontrol_tests.cpp4
-rw-r--r--src/test/transaction_tests.cpp6
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/test/uint256_tests.cpp2
-rw-r--r--src/test/versionbits_tests.cpp2
-rw-r--r--src/timedata.cpp4
-rw-r--r--src/txmempool.h6
-rw-r--r--src/util.cpp4
-rw-r--r--src/util.h2
-rw-r--r--src/validation.cpp24
-rw-r--r--src/validationinterface.cpp12
-rw-r--r--src/validationinterface.h15
-rw-r--r--src/wallet/coinselection.cpp4
-rw-r--r--src/wallet/rpcdump.cpp32
-rw-r--r--src/wallet/rpcwallet.cpp162
-rw-r--r--src/wallet/wallet.cpp77
-rw-r--r--src/wallet/wallet.h17
-rw-r--r--src/wallet/walletdb.cpp2
-rw-r--r--src/warnings.cpp10
-rw-r--r--src/warnings.h3
-rwxr-xr-xtest/functional/feature_block.py22
-rwxr-xr-xtest/functional/feature_pruning.py4
-rwxr-xr-xtest/functional/feature_segwit.py12
-rwxr-xr-xtest/functional/p2p_invalid_tx.py109
-rwxr-xr-xtest/functional/rpc_deprecated.py1
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py2
-rwxr-xr-xtest/functional/test_framework/mininode.py11
-rwxr-xr-xtest/functional/test_runner.py36
-rwxr-xr-xtest/functional/wallet_address_types.py5
-rwxr-xr-xtest/functional/wallet_basic.py165
-rwxr-xr-xtest/functional/wallet_import_rescan.py4
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py29
-rwxr-xr-xtest/functional/wallet_listreceivedby.py38
-rwxr-xr-xtest/functional/wallet_listsinceblock.py16
-rwxr-xr-xtest/functional/wallet_listtransactions.py117
-rwxr-xr-xtest/functional/wallet_txn_clone.py45
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py28
-rwxr-xr-xtest/util/rpcauth-test.py7
108 files changed, 1114 insertions, 990 deletions
diff --git a/.travis.yml b/.travis.yml
index 7f8bc638ff..48bcdf601b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -80,7 +80,7 @@ script:
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib
- if [ "$RUN_TESTS" = "true" ]; then travis_wait 50 make $MAKEJOBS check VERBOSE=1; fi
- if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude feature_pruning,feature_dbcrash"; fi
- - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet ${extended}; fi
+ - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; fi
after_script:
- echo $TRAVIS_COMMIT_RANGE
- echo $TRAVIS_COMMIT_LOG
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ea475f8cfb..c390595abf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,6 +14,9 @@ purposes. As such there are repository "maintainers" who are responsible for
merging pull requests as well as a "lead maintainer" who is responsible for the
release cycle, overall merging, moderation and appointment of maintainers.
+If you're looking for somewhere to start contributing, check out the
+[good first issue](https://github.com/bitcoin/bitcoin/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
+list.
Communication Channels
----------------------
diff --git a/configure.ac b/configure.ac
index b68fd8fc58..ce9e683eda 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,7 +84,7 @@ AC_PATH_TOOL(STRIP, strip)
AC_PATH_TOOL(GCOV, gcov)
AC_PATH_PROG(LCOV, lcov)
dnl Python 3.x is supported from 3.4 on (see https://github.com/bitcoin/bitcoin/issues/7893)
-AC_PATH_PROGS([PYTHON], [python3.6 python3.5 python3.4 python3 python2.7 python2 python])
+AC_PATH_PROGS([PYTHON], [python3.7 python3.6 python3.5 python3.4 python3 python])
AC_PATH_PROG(GENHTML, genhtml)
AC_PATH_PROG([GIT], [git])
AC_PATH_PROG(CCACHE,ccache)
diff --git a/contrib/devtools/lint-logs.sh b/contrib/devtools/lint-logs.sh
index 3bb54359a8..35be13ec19 100755
--- a/contrib/devtools/lint-logs.sh
+++ b/contrib/devtools/lint-logs.sh
@@ -13,12 +13,13 @@
# ignored
-UNTERMINATED_LOGS=$(git grep "LogPrintf(" -- "*.cpp" | \
+UNTERMINATED_LOGS=$(git grep --extended-regexp "LogPrintf?\(" -- "*.cpp" | \
grep -v '\\n"' | \
grep -v "/\* Continued \*/" | \
+ grep -v "LogPrint()" | \
grep -v "LogPrintf()")
if [[ ${UNTERMINATED_LOGS} != "" ]]; then
- echo "All calls to LogPrintf() should be terminated with \\n"
+ echo "All calls to LogPrintf() and LogPrint() should be terminated with \\n"
echo
echo "${UNTERMINATED_LOGS}"
exit 1
diff --git a/contrib/tidy_datadir.sh b/contrib/tidy_datadir.sh
deleted file mode 100755
index b845b34e41..0000000000
--- a/contrib/tidy_datadir.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2013 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-if [ -d "$1" ]; then
- cd "$1" || exit 1
-else
- echo "Usage: $0 <datadir>" >&2
- echo "Removes obsolete Bitcoin database files" >&2
- exit 1
-fi
-
-LEVEL=0
-if [ -f wallet.dat -a -f addr.dat -a -f blkindex.dat -a -f blk0001.dat ]; then LEVEL=1; fi
-if [ -f wallet.dat -a -f peers.dat -a -f blkindex.dat -a -f blk0001.dat ]; then LEVEL=2; fi
-if [ -f wallet.dat -a -f peers.dat -a -f coins/CURRENT -a -f blktree/CURRENT -a -f blocks/blk00000.dat ]; then LEVEL=3; fi
-if [ -f wallet.dat -a -f peers.dat -a -f chainstate/CURRENT -a -f blocks/index/CURRENT -a -f blocks/blk00000.dat ]; then LEVEL=4; fi
-
-case $LEVEL in
- 0)
- echo "Error: no Bitcoin datadir detected."
- exit 1
- ;;
- 1)
- echo "Detected old Bitcoin datadir (before 0.7)."
- echo "Nothing to do."
- exit 0
- ;;
- 2)
- echo "Detected Bitcoin 0.7 datadir."
- ;;
- 3)
- echo "Detected Bitcoin pre-0.8 datadir."
- ;;
- 4)
- echo "Detected Bitcoin 0.8 datadir."
- ;;
-esac
-
-FILES=""
-DIRS=""
-
-if [ $LEVEL -ge 3 ]; then FILES=$(echo $FILES blk????.dat blkindex.dat); fi
-if [ $LEVEL -ge 2 ]; then FILES=$(echo $FILES addr.dat); fi
-if [ $LEVEL -ge 4 ]; then DIRS=$(echo $DIRS coins blktree); fi
-
-for FILE in $FILES; do
- if [ -f $FILE ]; then
- echo "Deleting: $FILE"
- rm -f $FILE
- fi
-done
-
-for DIR in $DIRS; do
- if [ -d $DIR ]; then
- echo "Deleting: $DIR/"
- rm -rf $DIR
- fi
-done
-
-echo "Done."
diff --git a/doc/release-notes.md b/doc/release-notes.md
index e190c78609..7a9a98bfec 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -72,8 +72,8 @@ RPC changes
`getrawtransaction` RPC commands.
- New `fees` field introduced in `getrawmempool`, `getmempoolancestors`, `getmempooldescendants` and
`getmempoolentry` when verbosity is set to `true` with sub-fields `ancestor`, `base`, `modified`
- and `descendent` denominated in BTC. This new field deprecates previous fee fields, such as
- `fee`, `modifiedfee`, `ancestorfee` and `descendentfee`.
+ and `descendant` denominated in BTC. This new field deprecates previous fee fields, such as
+ `fee`, `modifiedfee`, `ancestorfee` and `descendantfee`.
External wallet files
---------------------
@@ -104,6 +104,21 @@ Low-level RPC changes
now the empty string `""` instead of `"wallet.dat"`. If bitcoin is started
with any `-wallet=<path>` options, there is no change in behavior, and the
name of any wallet is just its `<path>` string.
+- Passing an empty string (`""`) as the `address_type` parameter to
+ `getnewaddress`, `getrawchangeaddress`, `addmultisigaddress`,
+ `fundrawtransaction` RPCs is now an error. Previously, this would fall back
+ to using the default address type. It is still possible to pass null or leave
+ the parameter unset to use the default address type.
+
+- Bare multisig outputs to our keys are no longer automatically treated as
+ incoming payments. As this feature was only available for multisig outputs for
+ which you had all private keys in your wallet, there was generally no use for
+ them compared to single-key schemes. Furthermore, no address format for such
+ outputs is defined, and wallet software can't easily send to it. These outputs
+ will no longer show up in `listtransactions`, `listunspent`, or contribute to
+ your balance, unless they are explicitly watched (using `importaddress` or
+ `importmulti` with hex script argument). `signrawtransaction*` also still
+ works for them.
### Logging
diff --git a/doc/tor.md b/doc/tor.md
index 931c83abdd..f0f98b7d12 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -1,5 +1,4 @@
-TOR SUPPORT IN BITCOIN
-======================
+# TOR SUPPORT IN BITCOIN
It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
@@ -7,8 +6,7 @@ The following directions assume you have a Tor proxy running on port 9050. Many
configure Tor.
-1. Run bitcoin behind a Tor proxy
----------------------------------
+## 1. Run bitcoin behind a Tor proxy
The first step is running Bitcoin behind a Tor proxy. This will already make all
outgoing connections be anonymized, but more is possible.
@@ -34,12 +32,12 @@ In a typical situation, this suffices to run behind a Tor proxy:
./bitcoind -proxy=127.0.0.1:9050
-2. Run a bitcoin hidden server
-------------------------------
+## 2. Run a bitcoin hidden server
If you configure your Tor system accordingly, it is possible to make your node also
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
-config file):
+config file): *Needed for Tor version 0.2.7.0 and older versions of Tor only. For newer
+versions of Tor see [Section 3](#3-automatically-listen-on-tor).*
HiddenServiceDir /var/lib/tor/bitcoin-service/
HiddenServicePort 8333 127.0.0.1:8333
@@ -88,8 +86,7 @@ for normal IPv4/IPv6 communication, use:
./bitcoind -onion=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover
-3. Automatically listen on Tor
---------------------------------
+## 3. Automatically listen on Tor
Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket
API, to create and destroy 'ephemeral' hidden services programmatically.
@@ -115,8 +112,7 @@ which has the appropriate permissions. An alternative authentication method is t
of the `-torpassword` flag and a `hash-password` which can be enabled and specified in
Tor configuration.
-4. Privacy recommendations
----------------------------
+## 4. Privacy recommendations
- Do not add anything but bitcoin ports to the hidden service created in section 2.
If you run a web service too, create a new hidden service for that.
diff --git a/share/rpcauth/README.md b/share/rpcauth/README.md
index 389278a125..20d16f0a97 100644
--- a/share/rpcauth/README.md
+++ b/share/rpcauth/README.md
@@ -8,3 +8,7 @@ Create login credentials for a JSON-RPC user.
Usage:
./rpcauth.py <username>
+
+in which case the script will generate a password. To specify a custom password do:
+
+ ./rpcauth.py <username> <password>
diff --git a/share/rpcauth/rpcauth.py b/share/rpcauth/rpcauth.py
index da84deb5e2..566c55aba9 100755
--- a/share/rpcauth/rpcauth.py
+++ b/share/rpcauth/rpcauth.py
@@ -17,24 +17,27 @@ def generate_salt():
salt_sequence = [cryptogen.randrange(256) for _ in range(16)]
return ''.join([format(r, 'x') for r in salt_sequence])
-def generate_password(salt):
+def generate_password():
"""Create 32 byte b64 password"""
- password = base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
+ return base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
+def password_to_hmac(salt, password):
m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), 'SHA256')
- password_hmac = m.hexdigest()
-
- return password, password_hmac
+ return m.hexdigest()
def main():
if len(sys.argv) < 2:
- sys.stderr.write('Please include username as an argument.\n')
+ sys.stderr.write('Please include username (and an optional password, will generate one if not provided) as an argument.\n')
sys.exit(0)
username = sys.argv[1]
salt = generate_salt()
- password, password_hmac = generate_password(salt)
+ if len(sys.argv) > 2:
+ password = sys.argv[2]
+ else:
+ password = generate_password()
+ password_hmac = password_to_hmac(salt, password)
print('String to be appended to bitcoin.conf:')
print('rpcauth={0}:{1}${2}'.format(username, salt, password_hmac))
diff --git a/src/Makefile.am b/src/Makefile.am
index 0466d961c3..04bd75a2a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -137,7 +137,6 @@ BITCOIN_CORE_H = \
rpc/client.h \
rpc/mining.h \
rpc/protocol.h \
- rpc/safemode.h \
rpc/server.h \
rpc/rawtransaction.h \
rpc/register.h \
@@ -223,7 +222,6 @@ libbitcoin_server_a_SOURCES = \
rpc/misc.cpp \
rpc/net.cpp \
rpc/rawtransaction.cpp \
- rpc/safemode.cpp \
rpc/server.cpp \
script/sigcache.cpp \
timedata.cpp \
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 1d87883522..c1f3339830 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -46,7 +46,6 @@ main(int argc, char** argv)
RandomInit();
ECC_Start();
SetupEnvironment();
- fPrintToDebugLog = false; // don't want to write to debug.log file
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index d0f28d1a3e..3cfad1b2c4 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -48,7 +48,7 @@ static void PrevectorClear(benchmark::State& state)
}
template <typename T>
-void PrevectorResize(benchmark::State& state)
+static void PrevectorResize(benchmark::State& state)
{
while (state.KeepRunning()) {
prevector<28, T> t0;
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 26a9231308..34472a0e61 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -29,7 +29,7 @@ static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
static const int CONTINUE_EXECUTION=-1;
-std::string HelpMessageCli()
+static std::string HelpMessageCli()
{
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
@@ -138,7 +138,7 @@ struct HTTPReply
std::string body;
};
-const char *http_errorstring(int code)
+static const char *http_errorstring(int code)
{
switch(code) {
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
@@ -387,7 +387,7 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
return reply;
}
-int CommandLineRPC(int argc, char *argv[])
+static int CommandLineRPC(int argc, char *argv[])
{
std::string strPrint;
int nRet = 0;
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 0dc2dfbf7d..69de1a1666 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -40,7 +40,7 @@
* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
*/
-void WaitForShutdown()
+static void WaitForShutdown()
{
while (!ShutdownRequested())
{
@@ -53,7 +53,7 @@ void WaitForShutdown()
//
// Start
//
-bool AppInit(int argc, char* argv[])
+static bool AppInit(int argc, char* argv[])
{
bool fRet = false;
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 121d95af90..71762158f0 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -173,7 +173,7 @@ public:
// 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 SetBestChain debug.log lines)
+ // (the tx=... number in the ChainStateFlushed debug.log lines)
3.5 // * estimated number of transactions per second after that timestamp
};
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 6a8308f869..aade7e21ca 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -88,7 +88,7 @@ CScript ParseScript(const std::string& s)
}
// Check that all of the input and output scripts of a transaction contains valid opcodes
-bool CheckTxScriptsSanity(const CMutableTransaction& tx)
+static bool CheckTxScriptsSanity(const CMutableTransaction& tx)
{
// Check input scripts for non-coinbase txs
if (!CTransaction(tx).IsCoinBase()) {
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index b8b338dfbc..bd08b04c0f 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -364,8 +364,8 @@ bool InitHTTPServer()
// Update libevent's log handling. Returns false if our version of
// libevent doesn't support debug logging, in which case we should
// clear the BCLog::LIBEVENT flag.
- if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
- logCategories &= ~BCLog::LIBEVENT;
+ if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) {
+ g_logger->DisableCategory(BCLog::LIBEVENT);
}
#ifdef WIN32
diff --git a/src/httpserver.h b/src/httpserver.h
index f17be65962..8132c887b5 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -32,7 +32,7 @@ void InterruptHTTPServer();
/** Stop HTTP server */
void StopHTTPServer();
-/** Change logging level for libevent. Removes BCLog::LIBEVENT from logCategories if
+/** Change logging level for libevent. Removes BCLog::LIBEVENT from log categories if
* libevent doesn't support debug logging.*/
bool UpdateHTTPServerLogging(bool enable);
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 2a661f0330..5b6e0f9980 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -192,7 +192,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const C
}
}
-void TxIndex::SetBestChain(const CBlockLocator& locator)
+void TxIndex::ChainStateFlushed(const CBlockLocator& locator)
{
if (!m_synced) {
return;
@@ -211,7 +211,7 @@ void TxIndex::SetBestChain(const CBlockLocator& locator)
return;
}
- // This checks that SetBestChain callbacks are received after BlockConnected. The check may fail
+ // This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail
// immediately after the the sync thread catches up and sets m_synced. Consider the case where
// there is a reorg and the blocks on the stale branch are in the ValidationInterface queue
// backlog even after the sync thread has caught up to the new chain tip. In this unlikely
@@ -268,7 +268,9 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe
CBlockHeader header;
try {
file >> header;
- fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
+ if (fseek(file.Get(), postx.nTxOffset, SEEK_CUR)) {
+ return error("%s: fseek(...) failed", __func__);
+ }
file >> tx;
} catch (const std::exception& e) {
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
diff --git a/src/index/txindex.h b/src/index/txindex.h
index ac746de05b..4937bd64e9 100644
--- a/src/index/txindex.h
+++ b/src/index/txindex.h
@@ -55,7 +55,7 @@ protected:
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
const std::vector<CTransactionRef>& txn_conflicted) override;
- void SetBestChain(const CBlockLocator& locator) override;
+ void ChainStateFlushed(const CBlockLocator& locator) override;
public:
/// Constructs the TxIndex, which becomes available to be queried.
diff --git a/src/init.cpp b/src/init.cpp
index eca3577f27..7d8f462ef1 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -31,7 +31,6 @@
#include <policy/policy.h>
#include <rpc/server.h>
#include <rpc/register.h>
-#include <rpc/safemode.h>
#include <rpc/blockchain.h>
#include <script/standard.h>
#include <script/sigcache.h>
@@ -243,7 +242,7 @@ void Shutdown()
fFeeEstimatesInitialized = false;
}
- // FlushStateToDisk generates a SetBestChain callback, which we should avoid missing
+ // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
if (pcoinsTip != nullptr) {
FlushStateToDisk();
}
@@ -299,6 +298,7 @@ void Shutdown()
* The execution context the handler is invoked in is not guaranteed,
* so we restrict handler operations to just touching variables:
*/
+#ifndef WIN32
static void HandleSIGTERM(int)
{
fRequestShutdown = true;
@@ -306,8 +306,16 @@ static void HandleSIGTERM(int)
static void HandleSIGHUP(int)
{
- fReopenDebugLog = true;
+ g_logger->m_reopen_file = true;
+}
+#else
+static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
+{
+ fRequestShutdown = true;
+ Sleep(INFINITE);
+ return true;
}
+#endif
#ifndef WIN32
static void registerSignalHandler(int signal, void(*handler)(int))
@@ -320,12 +328,12 @@ static void registerSignalHandler(int signal, void(*handler)(int))
}
#endif
-void OnRPCStarted()
+static void OnRPCStarted()
{
uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange);
}
-void OnRPCStopped()
+static void OnRPCStopped()
{
uiInterface.NotifyBlockTip.disconnect(&RPCNotifyBlockChange);
RPCNotifyBlockChange(false, nullptr);
@@ -448,9 +456,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
- strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
strUsage += HelpMessageOpt("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used");
- strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
strUsage += HelpMessageOpt("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT));
@@ -598,7 +604,7 @@ struct CImportingNow
// rev files since they'll be rewritten by the reindex anyway. This ensures that vinfoBlockFile
// is in sync with what's actually on disk by the time we start downloading, so that pruning
// works correctly.
-void CleanupBlockRevFiles()
+static void CleanupBlockRevFiles()
{
std::map<std::string, fs::path> mapBlockFiles;
@@ -633,7 +639,7 @@ void CleanupBlockRevFiles()
}
}
-void ThreadImport(std::vector<fs::path> vImportFiles)
+static void ThreadImport(std::vector<fs::path> vImportFiles)
{
const CChainParams& chainparams = Params();
RenameThread("bitcoin-loadblk");
@@ -712,7 +718,7 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
* Ensure that Bitcoin is running in a usable environment with all
* necessary library support.
*/
-bool InitSanityCheck(void)
+static bool InitSanityCheck(void)
{
if(!ECC_InitSanityCheck()) {
InitError("Elliptic curve cryptography sanity check failure. Aborting.");
@@ -730,7 +736,7 @@ bool InitSanityCheck(void)
return true;
}
-bool AppInitServers()
+static bool AppInitServers()
{
RPCServer::OnStarted(&OnRPCStarted);
RPCServer::OnStopped(&OnRPCStopped);
@@ -829,15 +835,18 @@ static std::string ResolveErrMsg(const char * const optname, const std::string&
*/
void InitLogging()
{
+ g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
+ g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
+
// Add newlines to the logfile to distinguish this execution from the last
// one; called before console logging is set up, so this is only sent to
// debug.log.
LogPrintf("\n\n\n\n\n");
- fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
- fPrintToDebugLog = !gArgs.IsArgNegated("-debuglogfile");
- fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
- fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+ g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
+ g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
+ g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
+
fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
std::string version_string = FormatFullVersion();
@@ -912,6 +921,8 @@ bool AppInitBasicSetup()
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
signal(SIGPIPE, SIG_IGN);
+#else
+ SetConsoleCtrlHandler(consoleCtrlHandler, true);
#endif
std::set_new_handler(new_handler_terminate);
@@ -965,24 +976,18 @@ bool AppInitParameterInteraction()
if (std::none_of(categories.begin(), categories.end(),
[](std::string cat){return cat == "0" || cat == "none";})) {
for (const auto& cat : categories) {
- uint32_t flag = 0;
- if (!GetLogCategory(&flag, &cat)) {
+ if (!g_logger->EnableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
- continue;
}
- logCategories |= flag;
}
}
}
// Now remove the logging categories which were explicitly excluded
for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
- uint32_t flag = 0;
- if (!GetLogCategory(&flag, &cat)) {
+ if (!g_logger->DisableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
- continue;
}
- logCategories &= ~flag;
}
// Check for -debugnet
@@ -1233,18 +1238,19 @@ bool AppInitMain()
#ifndef WIN32
CreatePidFile(GetPidFile(), getpid());
#endif
- if (fPrintToDebugLog) {
- if (gArgs.GetBoolArg("-shrinkdebugfile", logCategories == BCLog::NONE)) {
+ if (g_logger->m_print_to_file) {
+ if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) {
// Do this first since it both loads a bunch of debug.log into memory,
// and because this needs to happen before any other debug.log printing
- ShrinkDebugFile();
+ g_logger->ShrinkDebugFile();
}
- if (!OpenDebugLog()) {
- return InitError(strprintf("Could not open debug log file %s", GetDebugLogPath().string()));
+ if (!g_logger->OpenDebugLog()) {
+ return InitError(strprintf("Could not open debug log file %s",
+ g_logger->m_file_path.string()));
}
}
- if (!fLogTimestamps)
+ if (!g_logger->m_log_timestamps)
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string());
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 55786c807f..53d2359caf 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -60,7 +60,7 @@ class NodeImpl : public Node
void initLogging() override { InitLogging(); }
void initParameterInteraction() override { InitParameterInteraction(); }
std::string getWarnings(const std::string& type) override { return GetWarnings(type); }
- uint32_t getLogCategories() override { return ::logCategories; }
+ uint32_t getLogCategories() override { return g_logger->GetCategoryMask(); }
bool baseInitialize() override
{
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
diff --git a/src/keystore.h b/src/keystore.h
index fa912cb195..c56e4751de 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -54,7 +54,7 @@ protected:
ScriptMap mapScripts;
WatchOnlySet setWatchOnly;
- void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey);
+ void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
public:
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
diff --git a/src/logging.cpp b/src/logging.cpp
index e481582321..e8e22cbf97 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -4,97 +4,93 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <logging.h>
-#include <util.h>
-#include <utilstrencodings.h>
-
-#include <list>
-#include <mutex>
+#include <utiltime.h>
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
-bool fPrintToConsole = false;
-bool fPrintToDebugLog = true;
-
-bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
-bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
-bool fLogIPs = DEFAULT_LOGIPS;
-std::atomic<bool> fReopenDebugLog(false);
-
-/** Log categories bitfield. */
-std::atomic<uint32_t> logCategories(0);
-/**
- * LogPrintf() has been broken a couple of times now
- * by well-meaning people adding mutexes in the most straightforward way.
- * It breaks because it may be called by global destructors during shutdown.
- * Since the order of destruction of static/global objects is undefined,
- * defining a mutex as a global object doesn't work (the mutex gets
- * destroyed, and then some later destructor calls OutputDebugStringF,
- * maybe indirectly, and you get a core dump at shutdown trying to lock
- * the mutex).
- */
-
-static std::once_flag debugPrintInitFlag;
-
/**
- * We use std::call_once() to make sure mutexDebugLog and
- * vMsgsBeforeOpenLog are initialized in a thread-safe manner.
+ * NOTE: the logger instances is leaked on exit. This is ugly, but will be
+ * cleaned up by the OS/libc. Defining a logger as a global object doesn't work
+ * since the order of destruction of static/global objects is undefined.
+ * Consider if the logger gets destroyed, and then some later destructor calls
+ * LogPrintf, maybe indirectly, and you get a core dump at shutdown trying to
+ * access the logger. When the shutdown sequence is fully audited and tested,
+ * explicit destruction of these objects can be implemented by changing this
+ * from a raw pointer to a std::unique_ptr.
*
- * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
- * are leaked on exit. This is ugly, but will be cleaned up by
- * the OS/libc. When the shutdown sequence is fully audited and
- * tested, explicit destruction of these objects can be implemented.
+ * This method of initialization was originally introduced in
+ * ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
*/
-static FILE* fileout = nullptr;
-static std::mutex* mutexDebugLog = nullptr;
-static std::list<std::string>* vMsgsBeforeOpenLog;
+BCLog::Logger* const g_logger = new BCLog::Logger();
+
+bool fLogIPs = DEFAULT_LOGIPS;
static int FileWriteStr(const std::string &str, FILE *fp)
{
return fwrite(str.data(), 1, str.size(), fp);
}
-static void DebugPrintInit()
+bool BCLog::Logger::OpenDebugLog()
{
- assert(mutexDebugLog == nullptr);
- mutexDebugLog = new std::mutex();
- vMsgsBeforeOpenLog = new std::list<std::string>;
+ std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
+
+ assert(m_fileout == nullptr);
+ assert(!m_file_path.empty());
+
+ m_fileout = fsbridge::fopen(m_file_path, "a");
+ if (!m_fileout) {
+ return false;
+ }
+
+ setbuf(m_fileout, nullptr); // unbuffered
+ // dump buffered messages from before we opened the log
+ while (!m_msgs_before_open.empty()) {
+ FileWriteStr(m_msgs_before_open.front(), m_fileout);
+ m_msgs_before_open.pop_front();
+ }
+
+ return true;
}
-fs::path GetDebugLogPath()
+void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)
{
- fs::path logfile(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
- return AbsPathForConfigVal(logfile);
+ m_categories |= flag;
}
-bool OpenDebugLog()
+bool BCLog::Logger::EnableCategory(const std::string& str)
{
- std::call_once(debugPrintInitFlag, &DebugPrintInit);
- std::lock_guard<std::mutex> scoped_lock(*mutexDebugLog);
+ BCLog::LogFlags flag;
+ if (!GetLogCategory(flag, str)) return false;
+ EnableCategory(flag);
+ return true;
+}
- assert(fileout == nullptr);
- assert(vMsgsBeforeOpenLog);
- fs::path pathDebug = GetDebugLogPath();
+void BCLog::Logger::DisableCategory(BCLog::LogFlags flag)
+{
+ m_categories &= ~flag;
+}
- fileout = fsbridge::fopen(pathDebug, "a");
- if (!fileout) {
- return false;
- }
+bool BCLog::Logger::DisableCategory(const std::string& str)
+{
+ BCLog::LogFlags flag;
+ if (!GetLogCategory(flag, str)) return false;
+ DisableCategory(flag);
+ return true;
+}
- setbuf(fileout, nullptr); // unbuffered
- // dump buffered messages from before we opened the log
- while (!vMsgsBeforeOpenLog->empty()) {
- FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
- vMsgsBeforeOpenLog->pop_front();
- }
+bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
+{
+ return (m_categories.load(std::memory_order_relaxed) & category) != 0;
+}
- delete vMsgsBeforeOpenLog;
- vMsgsBeforeOpenLog = nullptr;
- return true;
+bool BCLog::Logger::DefaultShrinkDebugFile() const
+{
+ return m_categories == BCLog::NONE;
}
struct CLogCategoryDesc
{
- uint32_t flag;
+ BCLog::LogFlags flag;
std::string category;
};
@@ -127,19 +123,17 @@ const CLogCategoryDesc LogCategories[] =
{BCLog::ALL, "all"},
};
-bool GetLogCategory(uint32_t *f, const std::string *str)
+bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
{
- if (f && str) {
- if (*str == "") {
- *f = BCLog::ALL;
+ if (str == "") {
+ flag = BCLog::ALL;
+ return true;
+ }
+ for (const CLogCategoryDesc& category_desc : LogCategories) {
+ if (category_desc.category == str) {
+ flag = category_desc.flag;
return true;
}
- for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
- if (LogCategories[i].category == *str) {
- *f = LogCategories[i].flag;
- return true;
- }
- }
}
return false;
}
@@ -148,11 +142,11 @@ std::string ListLogCategories()
{
std::string ret;
int outcount = 0;
- for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
+ for (const CLogCategoryDesc& category_desc : LogCategories) {
// Omit the special cases.
- if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) {
+ if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
if (outcount != 0) ret += ", ";
- ret += LogCategories[i].category;
+ ret += category_desc.category;
outcount++;
}
}
@@ -162,34 +156,29 @@ std::string ListLogCategories()
std::vector<CLogCategoryActive> ListActiveLogCategories()
{
std::vector<CLogCategoryActive> ret;
- for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
+ for (const CLogCategoryDesc& category_desc : LogCategories) {
// Omit the special cases.
- if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) {
+ if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
CLogCategoryActive catActive;
- catActive.category = LogCategories[i].category;
- catActive.active = LogAcceptCategory(LogCategories[i].flag);
+ catActive.category = category_desc.category;
+ catActive.active = LogAcceptCategory(category_desc.flag);
ret.push_back(catActive);
}
}
return ret;
}
-/**
- * fStartedNewLine is a state variable held by the calling context that will
- * suppress printing of the timestamp when multiple calls are made that don't
- * end in a newline. Initialize it to true, and hold it, in the calling context.
- */
-static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fStartedNewLine)
+std::string BCLog::Logger::LogTimestampStr(const std::string &str)
{
std::string strStamped;
- if (!fLogTimestamps)
+ if (!m_log_timestamps)
return str;
- if (*fStartedNewLine) {
+ if (m_started_new_line) {
int64_t nTimeMicros = GetTimeMicros();
strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
- if (fLogTimeMicros) {
+ if (m_log_time_micros) {
strStamped.pop_back();
strStamped += strprintf(".%06dZ", nTimeMicros%1000000);
}
@@ -202,63 +191,60 @@ static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fSt
strStamped = str;
if (!str.empty() && str[str.size()-1] == '\n')
- *fStartedNewLine = true;
+ m_started_new_line = true;
else
- *fStartedNewLine = false;
+ m_started_new_line = false;
return strStamped;
}
-int LogPrintStr(const std::string &str)
+void BCLog::Logger::LogPrintStr(const std::string &str)
{
- int ret = 0; // Returns total number of characters written
- static std::atomic_bool fStartedNewLine(true);
-
- std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
+ std::string strTimestamped = LogTimestampStr(str);
- if (fPrintToConsole) {
+ if (m_print_to_console) {
// print to console
- ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
+ fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
fflush(stdout);
}
- if (fPrintToDebugLog) {
- std::call_once(debugPrintInitFlag, &DebugPrintInit);
- std::lock_guard<std::mutex> scoped_lock(*mutexDebugLog);
+ if (m_print_to_file) {
+ std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
// buffer if we haven't opened the log yet
- if (fileout == nullptr) {
- assert(vMsgsBeforeOpenLog);
- ret = strTimestamped.length();
- vMsgsBeforeOpenLog->push_back(strTimestamped);
+ if (m_fileout == nullptr) {
+ m_msgs_before_open.push_back(strTimestamped);
}
else
{
// reopen the log file, if requested
- if (fReopenDebugLog) {
- fReopenDebugLog = false;
- fs::path pathDebug = GetDebugLogPath();
- if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr)
- setbuf(fileout, nullptr); // unbuffered
+ if (m_reopen_file) {
+ m_reopen_file = false;
+ m_fileout = fsbridge::freopen(m_file_path, "a", m_fileout);
+ if (!m_fileout) {
+ return;
+ }
+ setbuf(m_fileout, nullptr); // unbuffered
}
- ret = FileWriteStr(strTimestamped, fileout);
+ FileWriteStr(strTimestamped, m_fileout);
}
}
- return ret;
}
-void ShrinkDebugFile()
+void BCLog::Logger::ShrinkDebugFile()
{
// Amount of debug.log to save at end when shrinking (must fit in memory)
constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
+
+ assert(!m_file_path.empty());
+
// Scroll debug.log if it's getting too big
- fs::path pathLog = GetDebugLogPath();
- FILE* file = fsbridge::fopen(pathLog, "r");
+ FILE* file = fsbridge::fopen(m_file_path, "r");
// Special files (e.g. device nodes) may not have a size.
size_t log_size = 0;
try {
- log_size = fs::file_size(pathLog);
+ log_size = fs::file_size(m_file_path);
} catch (boost::filesystem::filesystem_error &) {}
// If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
@@ -267,11 +253,15 @@ void ShrinkDebugFile()
{
// Restart the file with some of the end
std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
- fseek(file, -((long)vch.size()), SEEK_END);
+ if (fseek(file, -((long)vch.size()), SEEK_END)) {
+ LogPrintf("Failed to shrink debug log file: fseek(...) failed\n");
+ fclose(file);
+ return;
+ }
int nBytes = fread(vch.data(), 1, vch.size(), file);
fclose(file);
- file = fsbridge::fopen(pathLog, "w");
+ file = fsbridge::fopen(m_file_path, "w");
if (file)
{
fwrite(vch.data(), 1, nBytes, file);
diff --git a/src/logging.h b/src/logging.h
index 4053f75acf..6400b131c2 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -11,6 +11,8 @@
#include <atomic>
#include <cstdint>
+#include <list>
+#include <mutex>
#include <string>
#include <vector>
@@ -19,15 +21,7 @@ static const bool DEFAULT_LOGIPS = false;
static const bool DEFAULT_LOGTIMESTAMPS = true;
extern const char * const DEFAULT_DEBUGLOGFILE;
-extern bool fPrintToConsole;
-extern bool fPrintToDebugLog;
-
-extern bool fLogTimestamps;
-extern bool fLogTimeMicros;
extern bool fLogIPs;
-extern std::atomic<bool> fReopenDebugLog;
-
-extern std::atomic<uint32_t> logCategories;
struct CLogCategoryActive
{
@@ -61,11 +55,65 @@ namespace BCLog {
LEVELDB = (1 << 20),
ALL = ~(uint32_t)0,
};
-}
+
+ class Logger
+ {
+ private:
+ FILE* m_fileout = nullptr;
+ std::mutex m_file_mutex;
+ std::list<std::string> m_msgs_before_open;
+
+ /**
+ * m_started_new_line is a state variable that will suppress printing of
+ * the timestamp when multiple calls are made that don't end in a
+ * newline.
+ */
+ std::atomic_bool m_started_new_line{true};
+
+ /** Log categories bitfield. */
+ std::atomic<uint32_t> m_categories{0};
+
+ std::string LogTimestampStr(const std::string& str);
+
+ public:
+ bool m_print_to_console = false;
+ bool m_print_to_file = false;
+
+ bool m_log_timestamps = DEFAULT_LOGTIMESTAMPS;
+ bool m_log_time_micros = DEFAULT_LOGTIMEMICROS;
+
+ fs::path m_file_path;
+ std::atomic<bool> m_reopen_file{false};
+
+ /** Send a string to the log output */
+ void LogPrintStr(const std::string &str);
+
+ /** Returns whether logs will be written to any output */
+ bool Enabled() const { return m_print_to_console || m_print_to_file; }
+
+ bool OpenDebugLog();
+ void ShrinkDebugFile();
+
+ uint32_t GetCategoryMask() const { return m_categories.load(); }
+
+ void EnableCategory(LogFlags flag);
+ bool EnableCategory(const std::string& str);
+ void DisableCategory(LogFlags flag);
+ bool DisableCategory(const std::string& str);
+
+ bool WillLogCategory(LogFlags category) const;
+
+ bool DefaultShrinkDebugFile() const;
+ };
+
+} // namespace BCLog
+
+extern BCLog::Logger* const g_logger;
+
/** Return true if log accepts specified category */
-static inline bool LogAcceptCategory(uint32_t category)
+static inline bool LogAcceptCategory(BCLog::LogFlags category)
{
- return (logCategories.load(std::memory_order_relaxed) & category) != 0;
+ return g_logger->WillLogCategory(category);
}
/** Returns a string with the log categories. */
@@ -74,11 +122,8 @@ std::string ListLogCategories();
/** Returns a vector of the active log categories. */
std::vector<CLogCategoryActive> ListActiveLogCategories();
-/** Return true if str parses as a log category and set the flags in f */
-bool GetLogCategory(uint32_t *f, const std::string *str);
-
-/** Send a string to the log output */
-int LogPrintStr(const std::string &str);
+/** Return true if str parses as a log category and set the flag */
+bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
/** Get format string from VA_ARGS for error reporting */
template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
@@ -99,7 +144,7 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
#define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0)
#else
#define LogPrintf(...) do { \
- if (fPrintToConsole || fPrintToDebugLog) { \
+ if (g_logger->Enabled()) { \
std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
try { \
_log_msg_ = tfm::format(__VA_ARGS__); \
@@ -107,7 +152,7 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
/* Original format string will have newline so don't add one here */ \
_log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
} \
- LogPrintStr(_log_msg_); \
+ g_logger->LogPrintStr(_log_msg_); \
} \
} while(0)
@@ -118,8 +163,4 @@ template<typename T, typename... Args> static inline void MarkUsed(const T& t, c
} while(0)
#endif
-fs::path GetDebugLogPath();
-bool OpenDebugLog();
-void ShrinkDebugFile();
-
#endif // BITCOIN_LOGGING_H
diff --git a/src/net.cpp b/src/net.cpp
index cd076c1ce2..55043ffe30 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -160,7 +160,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
return ret;
}
-int GetnScore(const CService& addr)
+static int GetnScore(const CService& addr)
{
LOCK(cs_mapLocalHost);
if (mapLocalHost.count(addr) == LOCAL_NONE)
@@ -395,7 +395,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
if (!addrConnect.IsValid()) {
- LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s", addrConnect.ToString(), pszDest);
+ LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
return nullptr;
}
// It is possible that we already have a connection to the IP/port pszDest resolved to.
@@ -1466,7 +1466,7 @@ void CConnman::WakeMessageHandler()
#ifdef USE_UPNP
static CThreadInterrupt g_upnp_interrupt;
static std::thread g_upnp_thread;
-void ThreadMapPort()
+static void ThreadMapPort()
{
std::string port = strprintf("%u", GetListenPort());
const char * multicastif = nullptr;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index ee4e9e61bc..ed2fb598d2 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -277,7 +277,7 @@ CNodeState *State(NodeId pnode) {
return &it->second;
}
-void UpdatePreferredDownload(CNode* node, CNodeState* state)
+static void UpdatePreferredDownload(CNode* node, CNodeState* state)
{
nPreferredDownload -= state->fPreferredDownload;
@@ -287,7 +287,7 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
+static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
{
ServiceFlags nLocalNodeServices = pnode->GetLocalServices();
uint64_t nonce = pnode->GetLocalNonce();
@@ -311,7 +311,7 @@ void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
// Requires cs_main.
// Returns a bool indicating whether we requested this block.
// Also used if a block was /not/ received and timed out or started with another peer
-bool MarkBlockAsReceived(const uint256& hash) {
+static bool MarkBlockAsReceived(const uint256& hash) {
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
@@ -337,7 +337,7 @@ bool MarkBlockAsReceived(const uint256& hash) {
// Requires cs_main.
// returns false, still setting pit, if the block was already in flight from the same peer
// pit will only be valid as long as the same cs_main lock is being held
-bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) {
+static bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) {
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -371,7 +371,7 @@ bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex*
}
/** Check whether the last unknown block a peer advertised is not yet known. */
-void ProcessBlockAvailability(NodeId nodeid) {
+static void ProcessBlockAvailability(NodeId nodeid) {
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -387,7 +387,7 @@ void ProcessBlockAvailability(NodeId nodeid) {
}
/** Update tracking information about which blocks a peer is assumed to have. */
-void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
+static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -411,7 +411,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
* lNodesAnnouncingHeaderAndIDs, and keeping that list under a certain size by
* removing the first element if necessary.
*/
-void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) {
+static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) {
AssertLockHeld(cs_main);
CNodeState* nodestate = State(nodeid);
if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
@@ -444,7 +444,7 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) {
}
}
-bool TipMayBeStale(const Consensus::Params &consensusParams)
+static bool TipMayBeStale(const Consensus::Params &consensusParams)
{
AssertLockHeld(cs_main);
if (g_last_tip_update == 0) {
@@ -454,13 +454,13 @@ bool TipMayBeStale(const Consensus::Params &consensusParams)
}
// Requires cs_main
-bool CanDirectFetch(const Consensus::Params &consensusParams)
+static bool CanDirectFetch(const Consensus::Params &consensusParams)
{
return chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
}
// Requires cs_main
-bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex)
+static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex)
{
if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
return true;
@@ -471,7 +471,7 @@ bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex)
/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
* at most count entries. */
-void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) {
+static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) {
if (count == 0)
return;
@@ -570,7 +570,7 @@ void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)
// Returns true for outbound peers, excluding manual connections, feelers, and
// one-shots
-bool IsOutboundDisconnectionCandidate(const CNode *node)
+static bool IsOutboundDisconnectionCandidate(const CNode *node)
{
return !(node->fInbound || node->m_manual_connection || node->fFeeler || node->fOneShot);
}
@@ -642,7 +642,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
// mapOrphanTransactions
//
-void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
+static void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
{
size_t max_extra_txn = gArgs.GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN);
if (max_extra_txn <= 0)
@@ -1280,7 +1280,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-uint32_t GetFetchFlags(CNode* pfrom) {
+static uint32_t GetFetchFlags(CNode* pfrom) {
uint32_t nFetchFlags = 0;
if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) {
nFetchFlags |= MSG_WITNESS_FLAG;
@@ -1571,6 +1571,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrint(BCLog::NET, "Unparseable reject message received\n");
}
}
+ return true;
}
else if (strCommand == NetMsgType::VERSION)
@@ -2059,7 +2060,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
const CBlockIndex* pindex = LookupBlockIndex(req.blockhash);
if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId());
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom->GetId());
return true;
}
@@ -2071,7 +2072,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// might maliciously send lots of getblocktxn requests to trigger
// expensive disk reads, because it will require the peer to
// actually receive all the data read from disk over the network.
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->GetId(), MAX_BLOCKTXN_DEPTH);
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom->GetId(), MAX_BLOCKTXN_DEPTH);
CInv inv;
inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
inv.hash = req.blockhash;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 57835b5427..15f9016be8 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -289,7 +289,7 @@ struct ProxyCredentials
};
/** Convert SOCKS5 reply to an error message */
-std::string Socks5ErrorString(uint8_t err)
+static std::string Socks5ErrorString(uint8_t err)
{
switch(err) {
case SOCKS5Reply::GENFAILURE:
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index b10532addf..c0a25f75b5 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -23,6 +23,6 @@ bool SignalsOptInRBF(const CTransaction &tx);
// according to BIP 125
// This involves checking sequence numbers of the transaction, as well
// as the sequence numbers of all in-mempool ancestors.
-RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool);
+RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
#endif // BITCOIN_POLICY_RBF_H
diff --git a/src/qt/README.md b/src/qt/README.md
index 7c23ccadcc..d8acf96ceb 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -16,7 +16,7 @@ To run:
### forms
-Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#use-qt-Creator-as IDE), but can be edited using any text editor.
+Contains [Designer UI](http://doc.qt.io/qt-5.9/designer-using-a-ui-file.html) files. They are created with [Qt Creator](#using-qt-creator-as-ide), but can be edited using any text editor.
### locale
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index f38e864b48..25b615e6f8 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -159,7 +159,7 @@ public:
};
AddressTableModel::AddressTableModel(WalletModel *parent) :
- QAbstractTableModel(parent),walletModel(parent),priv(0)
+ QAbstractTableModel(parent), walletModel(parent)
{
columns << tr("Label") << tr("Address");
priv = new AddressTablePriv(this);
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 979f861fea..6e1b53b049 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -83,10 +83,10 @@ public:
OutputType GetDefaultAddressType() const;
private:
- WalletModel *walletModel;
- AddressTablePriv *priv;
+ WalletModel* const walletModel;
+ AddressTablePriv *priv = nullptr;
QStringList columns;
- EditStatus editStatus;
+ EditStatus editStatus = OK;
/** Look up address book data given an address string. */
bool getAddressData(const QString &address, std::string* name, std::string* purpose) const;
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 70cdb3361c..59bb5d5bb6 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -648,7 +648,7 @@ void PaymentServer::fetchPaymentACK(WalletModel* walletModel, const SendCoinsRec
// use for change. Despite an actual payment and not change, this is a close match:
// it's the output type we use subject to privacy issues, but not restricted by what
// other software supports.
- const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::NONE ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType();
+ const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::CHANGE_AUTO ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType();
walletModel->wallet().learnRelatedScripts(newKey, change_type);
CTxDestination dest = GetDestinationForKey(newKey, change_type);
std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString();
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 5122bab36f..7924840d0b 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -455,12 +455,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
QWidget(parent),
m_node(node),
ui(new Ui::RPCConsole),
- clientModel(0),
- historyPtr(0),
- platformStyle(_platformStyle),
- peersTableContextMenu(0),
- banTableContextMenu(0),
- consoleFontSize(0)
+ platformStyle(_platformStyle)
{
ui->setupUi(this);
QSettings settings;
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a9a60d09f1..a53c4c24f9 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -145,18 +145,18 @@ private:
};
interfaces::Node& m_node;
- Ui::RPCConsole *ui;
- ClientModel *clientModel;
+ Ui::RPCConsole* const ui;
+ ClientModel *clientModel = nullptr;
QStringList history;
- int historyPtr;
+ int historyPtr = 0;
QString cmdBeforeBrowsing;
QList<NodeId> cachedNodeids;
- const PlatformStyle *platformStyle;
- RPCTimerInterface *rpcTimerInterface;
- QMenu *peersTableContextMenu;
- QMenu *banTableContextMenu;
- int consoleFontSize;
- QCompleter *autoCompleter;
+ const PlatformStyle* const platformStyle;
+ RPCTimerInterface *rpcTimerInterface = nullptr;
+ QMenu *peersTableContextMenu = nullptr;
+ QMenu *banTableContextMenu = nullptr;
+ int consoleFontSize = 0;
+ QCompleter *autoCompleter = nullptr;
QThread thread;
QString m_last_wallet_id;
diff --git a/src/random.cpp b/src/random.cpp
index b004dcac39..4ba86e4e7a 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -178,7 +178,7 @@ static void RandAddSeedPerfmon()
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
* compatible way to get cryptographic randomness on UNIX-ish platforms.
*/
-void GetDevURandom(unsigned char *ent32)
+static void GetDevURandom(unsigned char *ent32)
{
int f = open("/dev/urandom", O_RDONLY);
if (f == -1) {
diff --git a/src/rest.cpp b/src/rest.cpp
index 095655b3a0..ffa75c241f 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -33,7 +33,7 @@ enum class RetFormat {
};
static const struct {
- enum RetFormat rf;
+ RetFormat rf;
const char* name;
} rf_names[] = {
{RetFormat::UNDEF, ""},
@@ -68,7 +68,7 @@ static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string me
return false;
}
-static enum RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
+static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
{
const std::string::size_type pos = strReq.rfind('.');
if (pos == std::string::npos)
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 03c097197f..a2d8ce1557 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -157,7 +157,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
return result;
}
-UniValue getblockcount(const JSONRPCRequest& request)
+static UniValue getblockcount(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -174,7 +174,7 @@ UniValue getblockcount(const JSONRPCRequest& request)
return chainActive.Height();
}
-UniValue getbestblockhash(const JSONRPCRequest& request)
+static UniValue getbestblockhash(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -201,7 +201,7 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
cond_blockchange.notify_all();
}
-UniValue waitfornewblock(const JSONRPCRequest& request)
+static UniValue waitfornewblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
@@ -239,7 +239,7 @@ UniValue waitfornewblock(const JSONRPCRequest& request)
return ret;
}
-UniValue waitforblock(const JSONRPCRequest& request)
+static UniValue waitforblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -281,7 +281,7 @@ UniValue waitforblock(const JSONRPCRequest& request)
return ret;
}
-UniValue waitforblockheight(const JSONRPCRequest& request)
+static UniValue waitforblockheight(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -323,7 +323,7 @@ UniValue waitforblockheight(const JSONRPCRequest& request)
return ret;
}
-UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
+static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 0) {
throw std::runtime_error(
@@ -338,7 +338,7 @@ UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue getdifficulty(const JSONRPCRequest& request)
+static UniValue getdifficulty(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -355,7 +355,7 @@ UniValue getdifficulty(const JSONRPCRequest& request)
return GetDifficulty();
}
-std::string EntryDescriptionString()
+static std::string EntryDescriptionString()
{
return " \"size\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n"
" \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n"
@@ -373,7 +373,7 @@ std::string EntryDescriptionString()
" \"base\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
" \"modified\" : n, (numeric) transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT + "\n"
" \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n"
- " \"descendent\" : n, (numeric) number of in-mempool ancestor transactions (including this one) in " + CURRENCY_UNIT + "\n"
+ " \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n"
" }\n"
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
" \"transactionid\", (string) parent transaction id\n"
@@ -383,7 +383,7 @@ std::string EntryDescriptionString()
" ... ]\n";
}
-void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
+static void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
{
AssertLockHeld(mempool.cs);
@@ -460,7 +460,7 @@ UniValue mempoolToJSON(bool fVerbose)
}
}
-UniValue getrawmempool(const JSONRPCRequest& request)
+static UniValue getrawmempool(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
@@ -492,7 +492,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
return mempoolToJSON(fVerbose);
}
-UniValue getmempoolancestors(const JSONRPCRequest& request)
+static UniValue getmempoolancestors(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
@@ -556,7 +556,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request)
}
}
-UniValue getmempooldescendants(const JSONRPCRequest& request)
+static UniValue getmempooldescendants(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
@@ -620,7 +620,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request)
}
}
-UniValue getmempoolentry(const JSONRPCRequest& request)
+static UniValue getmempoolentry(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
@@ -653,7 +653,7 @@ UniValue getmempoolentry(const JSONRPCRequest& request)
return info;
}
-UniValue getblockhash(const JSONRPCRequest& request)
+static UniValue getblockhash(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -678,7 +678,7 @@ UniValue getblockhash(const JSONRPCRequest& request)
return pblockindex->GetBlockHash().GetHex();
}
-UniValue getblockheader(const JSONRPCRequest& request)
+static UniValue getblockheader(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -737,7 +737,7 @@ UniValue getblockheader(const JSONRPCRequest& request)
return blockheaderToJSON(pblockindex);
}
-UniValue getblock(const JSONRPCRequest& request)
+static UniValue getblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -899,7 +899,7 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
return true;
}
-UniValue pruneblockchain(const JSONRPCRequest& request)
+static UniValue pruneblockchain(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -940,7 +940,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
else if (height > chainHeight)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height.");
else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) {
- LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.");
+ LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.\n");
height = chainHeight - MIN_BLOCKS_TO_KEEP;
}
@@ -948,7 +948,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
return uint64_t(height);
}
-UniValue gettxoutsetinfo(const JSONRPCRequest& request)
+static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -1069,7 +1069,7 @@ UniValue gettxout(const JSONRPCRequest& request)
return ret;
}
-UniValue verifychain(const JSONRPCRequest& request)
+static UniValue verifychain(const JSONRPCRequest& request)
{
int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL);
int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS);
@@ -1159,7 +1159,7 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
return rv;
}
-void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// Deployments with timeout value of 0 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
@@ -1285,7 +1285,7 @@ struct CompareBlocksByHeight
}
};
-UniValue getchaintips(const JSONRPCRequest& request)
+static UniValue getchaintips(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -1402,7 +1402,7 @@ UniValue mempoolInfoToJSON()
return ret;
}
-UniValue getmempoolinfo(const JSONRPCRequest& request)
+static UniValue getmempoolinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -1425,7 +1425,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request)
return mempoolInfoToJSON();
}
-UniValue preciousblock(const JSONRPCRequest& request)
+static UniValue preciousblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -1463,7 +1463,7 @@ UniValue preciousblock(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue invalidateblock(const JSONRPCRequest& request)
+static UniValue invalidateblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -1502,7 +1502,7 @@ UniValue invalidateblock(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue reconsiderblock(const JSONRPCRequest& request)
+static UniValue reconsiderblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -1540,7 +1540,7 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue getchaintxstats(const JSONRPCRequest& request)
+static UniValue getchaintxstats(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
@@ -1614,7 +1614,7 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
return ret;
}
-UniValue savemempool(const JSONRPCRequest& request)
+static UniValue savemempool(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index b4bb78e689..45ec501b9d 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -44,7 +44,7 @@ unsigned int ParseConfirmTarget(const UniValue& value)
* or from the last difficulty change if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
-UniValue GetNetworkHashPS(int lookup, int height) {
+static UniValue GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
@@ -81,7 +81,7 @@ UniValue GetNetworkHashPS(int lookup, int height) {
return workDiff.getdouble() / timeDiff;
}
-UniValue getnetworkhashps(const JSONRPCRequest& request)
+static UniValue getnetworkhashps(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
@@ -151,7 +151,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
return blockHashes;
}
-UniValue generatetoaddress(const JSONRPCRequest& request)
+static UniValue generatetoaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
throw std::runtime_error(
@@ -185,7 +185,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request)
return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
}
-UniValue getmininginfo(const JSONRPCRequest& request)
+static UniValue getmininginfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -224,7 +224,7 @@ UniValue getmininginfo(const JSONRPCRequest& request)
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
-UniValue prioritisetransaction(const JSONRPCRequest& request)
+static UniValue prioritisetransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
@@ -278,7 +278,7 @@ static UniValue BIP22ValidationResult(const CValidationState& state)
return "valid?";
}
-std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
+static std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
std::string s = vbinfo.name;
if (!vbinfo.gbt_force) {
@@ -287,7 +287,7 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
return s;
}
-UniValue getblocktemplate(const JSONRPCRequest& request)
+static UniValue getblocktemplate(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
@@ -694,7 +694,7 @@ protected:
}
};
-UniValue submitblock(const JSONRPCRequest& request)
+static UniValue submitblock(const JSONRPCRequest& request)
{
// We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
@@ -764,13 +764,13 @@ UniValue submitblock(const JSONRPCRequest& request)
return BIP22ValidationResult(sc.state);
}
-UniValue estimatefee(const JSONRPCRequest& request)
+static UniValue estimatefee(const JSONRPCRequest& request)
{
throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n"
"Clients should use estimatesmartfee.");
}
-UniValue estimatesmartfee(const JSONRPCRequest& request)
+static UniValue estimatesmartfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -831,7 +831,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
return result;
}
-UniValue estimaterawfee(const JSONRPCRequest& request)
+static UniValue estimaterawfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 6754407dbd..6772784d3d 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -33,7 +33,7 @@
#include <univalue.h>
-UniValue validateaddress(const JSONRPCRequest& request)
+static UniValue validateaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -90,7 +90,7 @@ UniValue validateaddress(const JSONRPCRequest& request)
// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
class CWallet;
-UniValue createmultisig(const JSONRPCRequest& request)
+static UniValue createmultisig(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
{
@@ -145,7 +145,7 @@ UniValue createmultisig(const JSONRPCRequest& request)
return result;
}
-UniValue verifymessage(const JSONRPCRequest& request)
+static UniValue verifymessage(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
@@ -201,7 +201,7 @@ UniValue verifymessage(const JSONRPCRequest& request)
return (pubkey.GetID() == *keyID);
}
-UniValue signmessagewithprivkey(const JSONRPCRequest& request)
+static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
@@ -240,7 +240,7 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request)
return EncodeBase64(vchSig.data(), vchSig.size());
}
-UniValue setmocktime(const JSONRPCRequest& request)
+static UniValue setmocktime(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -299,7 +299,7 @@ static std::string RPCMallocInfo()
}
#endif
-UniValue getmemoryinfo(const JSONRPCRequest& request)
+static UniValue getmemoryinfo(const JSONRPCRequest& request)
{
/* Please, avoid using the word "pool" here in the RPC interface or help,
* as users will undoubtedly confuse it with the other "memory pool"
@@ -346,21 +346,22 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
}
}
-uint32_t getCategoryMask(UniValue cats) {
+static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
cats = cats.get_array();
- uint32_t mask = 0;
for (unsigned int i = 0; i < cats.size(); ++i) {
- uint32_t flag = 0;
std::string cat = cats[i].get_str();
- if (!GetLogCategory(&flag, &cat)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
+
+ bool success;
+ if (enable) {
+ success = g_logger->EnableCategory(cat);
+ } else {
+ success = g_logger->DisableCategory(cat);
}
- if (flag == BCLog::NONE) {
- return 0;
+
+ if (!success) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
}
- mask |= flag;
}
- return mask;
}
UniValue logging(const JSONRPCRequest& request)
@@ -399,25 +400,25 @@ UniValue logging(const JSONRPCRequest& request)
);
}
- uint32_t originalLogCategories = logCategories;
+ uint32_t original_log_categories = g_logger->GetCategoryMask();
if (request.params[0].isArray()) {
- logCategories |= getCategoryMask(request.params[0]);
+ EnableOrDisableLogCategories(request.params[0], true);
}
-
if (request.params[1].isArray()) {
- logCategories &= ~getCategoryMask(request.params[1]);
+ EnableOrDisableLogCategories(request.params[1], false);
}
+ uint32_t updated_log_categories = g_logger->GetCategoryMask();
+ uint32_t changed_log_categories = original_log_categories ^ updated_log_categories;
// Update libevent logging if BCLog::LIBEVENT has changed.
// If the library version doesn't allow it, UpdateHTTPServerLogging() returns false,
// in which case we should clear the BCLog::LIBEVENT flag.
// Throw an error if the user has explicitly asked to change only the libevent
// flag and it failed.
- uint32_t changedLogCategories = originalLogCategories ^ logCategories;
- if (changedLogCategories & BCLog::LIBEVENT) {
- if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
- logCategories &= ~BCLog::LIBEVENT;
- if (changedLogCategories == BCLog::LIBEVENT) {
+ if (changed_log_categories & BCLog::LIBEVENT) {
+ if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) {
+ g_logger->DisableCategory(BCLog::LIBEVENT);
+ if (changed_log_categories == BCLog::LIBEVENT) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
}
}
@@ -432,7 +433,7 @@ UniValue logging(const JSONRPCRequest& request)
return result;
}
-UniValue echo(const JSONRPCRequest& request)
+static UniValue echo(const JSONRPCRequest& request)
{
if (request.fHelp)
throw std::runtime_error(
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index fee2b765ba..1530d8578b 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -23,7 +23,7 @@
#include <univalue.h>
-UniValue getconnectioncount(const JSONRPCRequest& request)
+static UniValue getconnectioncount(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -42,7 +42,7 @@ UniValue getconnectioncount(const JSONRPCRequest& request)
return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
}
-UniValue ping(const JSONRPCRequest& request)
+static UniValue ping(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -65,7 +65,7 @@ UniValue ping(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue getpeerinfo(const JSONRPCRequest& request)
+static UniValue getpeerinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -190,7 +190,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
return ret;
}
-UniValue addnode(const JSONRPCRequest& request)
+static UniValue addnode(const JSONRPCRequest& request)
{
std::string strCommand;
if (!request.params[1].isNull())
@@ -237,7 +237,7 @@ UniValue addnode(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue disconnectnode(const JSONRPCRequest& request)
+static UniValue disconnectnode(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3)
throw std::runtime_error(
@@ -280,7 +280,7 @@ UniValue disconnectnode(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue getaddednodeinfo(const JSONRPCRequest& request)
+static UniValue getaddednodeinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
@@ -347,7 +347,7 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request)
return ret;
}
-UniValue getnettotals(const JSONRPCRequest& request)
+static UniValue getnettotals(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 0)
throw std::runtime_error(
@@ -413,7 +413,7 @@ static UniValue GetNetworksInfo()
return networks;
}
-UniValue getnetworkinfo(const JSONRPCRequest& request)
+static UniValue getnetworkinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -489,7 +489,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request)
return obj;
}
-UniValue setban(const JSONRPCRequest& request)
+static UniValue setban(const JSONRPCRequest& request)
{
std::string strCommand;
if (!request.params[1].isNull())
@@ -553,7 +553,7 @@ UniValue setban(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue listbanned(const JSONRPCRequest& request)
+static UniValue listbanned(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -586,7 +586,7 @@ UniValue listbanned(const JSONRPCRequest& request)
return bannedAddresses;
}
-UniValue clearbanned(const JSONRPCRequest& request)
+static UniValue clearbanned(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -604,7 +604,7 @@ UniValue clearbanned(const JSONRPCRequest& request)
return NullUniValue;
}
-UniValue setnetworkactive(const JSONRPCRequest& request)
+static UniValue setnetworkactive(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index 4a265735d2..6954aed252 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -46,7 +46,6 @@ enum RPCErrorCode
//! General application defined errors
RPC_MISC_ERROR = -1, //!< std::exception thrown in command handling
- RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode
RPC_TYPE_ERROR = -3, //!< Unexpected type was passed as parameter
RPC_INVALID_ADDRESS_OR_KEY = -5, //!< Invalid address or key
RPC_OUT_OF_MEMORY = -7, //!< Ran out of memory during operation
@@ -88,6 +87,9 @@ enum RPCErrorCode
//! Backwards compatible aliases
RPC_WALLET_INVALID_ACCOUNT_NAME = RPC_WALLET_INVALID_LABEL_NAME,
+
+ //! Unused reserved codes, kept around for backwards compatibility. Do not reuse.
+ RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode
};
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 0cb34a0cca..c5185ca599 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -19,7 +19,6 @@
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <rpc/rawtransaction.h>
-#include <rpc/safemode.h>
#include <rpc/server.h>
#include <script/script.h>
#include <script/script_error.h>
@@ -38,7 +37,7 @@
#include <univalue.h>
-void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
+static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
@@ -64,7 +63,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
}
}
-UniValue getrawtransaction(const JSONRPCRequest& request)
+static UniValue getrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
@@ -204,7 +203,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
return result;
}
-UniValue gettxoutproof(const JSONRPCRequest& request)
+static UniValue gettxoutproof(const JSONRPCRequest& request)
{
if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
throw std::runtime_error(
@@ -298,7 +297,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
return strHex;
}
-UniValue verifytxoutproof(const JSONRPCRequest& request)
+static UniValue verifytxoutproof(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -334,7 +333,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
return res;
}
-UniValue createrawtransaction(const JSONRPCRequest& request)
+static UniValue createrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
throw std::runtime_error(
@@ -494,7 +493,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
return EncodeHexTx(rawTx);
}
-UniValue decoderawtransaction(const JSONRPCRequest& request)
+static UniValue decoderawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -570,7 +569,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
return result;
}
-UniValue decodescript(const JSONRPCRequest& request)
+static UniValue decodescript(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
@@ -668,7 +667,7 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
vErrorsRet.push_back(entry);
}
-UniValue combinerawtransaction(const JSONRPCRequest& request)
+static UniValue combinerawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
@@ -907,7 +906,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
return result;
}
-UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
+static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
@@ -1085,7 +1084,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
}
}
-UniValue sendrawtransaction(const JSONRPCRequest& request)
+static UniValue sendrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -1108,8 +1107,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
);
- ObserveSafeMode();
-
std::promise<void> promise;
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
@@ -1182,7 +1179,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
return hashTx.GetHex();
}
-UniValue testmempoolaccept(const JSONRPCRequest& request)
+static UniValue testmempoolaccept(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
@@ -1217,8 +1214,6 @@ UniValue testmempoolaccept(const JSONRPCRequest& request)
);
}
- ObserveSafeMode();
-
RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VBOOL});
if (request.params[0].get_array().size() != 1) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
diff --git a/src/rpc/safemode.cpp b/src/rpc/safemode.cpp
deleted file mode 100644
index 9f3a9d30b8..0000000000
--- a/src/rpc/safemode.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <rpc/safemode.h>
-
-#include <rpc/protocol.h>
-#include <util.h>
-#include <warnings.h>
-
-void ObserveSafeMode()
-{
- std::string warning = GetWarnings("rpc");
- if (warning != "" && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE)) {
- throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + warning);
- }
-}
-
diff --git a/src/rpc/safemode.h b/src/rpc/safemode.h
deleted file mode 100644
index 8466d6b2f9..0000000000
--- a/src/rpc/safemode.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2017 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_RPC_SAFEMODE_H
-#define BITCOIN_RPC_SAFEMODE_H
-
-static const bool DEFAULT_DISABLE_SAFEMODE = true;
-
-void ObserveSafeMode();
-
-#endif // BITCOIN_RPC_SAFEMODE_H
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index c7c3b1f0d3..7edd51d3d7 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -239,7 +239,7 @@ UniValue stop(const JSONRPCRequest& jsonRequest)
return "Bitcoin server stopping";
}
-UniValue uptime(const JSONRPCRequest& jsonRequest)
+static UniValue uptime(const JSONRPCRequest& jsonRequest)
{
if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
throw std::runtime_error(
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index b826bcfe20..fefa02fdef 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -13,34 +13,36 @@
typedef std::vector<unsigned char> valtype;
-static bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
-{
- for (const valtype& pubkey : pubkeys) {
- CKeyID keyID = CPubKey(pubkey).GetID();
- if (!keystore.HaveKey(keyID)) return false;
- }
- return true;
-}
+namespace {
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
+/**
+ * This is an enum that tracks the execution context of a script, similar to
+ * SigVersion in script/interpreter. It is separate however because we want to
+ * distinguish between top-level scriptPubKey execution and P2SH redeemScript
+ * execution (a distinction that has no impact on consensus rules).
+ */
+enum class IsMineSigVersion
{
- bool isInvalid = false;
- return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
-}
+ TOP = 0, //! scriptPubKey execution
+ P2SH = 1, //! P2SH redeemScript
+ WITNESS_V0 = 2 //! P2WSH witness script execution
+};
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
+bool PermitsUncompressed(IsMineSigVersion sigversion)
{
- bool isInvalid = false;
- return IsMine(keystore, dest, isInvalid, sigversion);
+ return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
}
-isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
+bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
{
- CScript script = GetScriptForDestination(dest);
- return IsMine(keystore, script, isInvalid, sigversion);
+ for (const valtype& pubkey : pubkeys) {
+ CKeyID keyID = CPubKey(pubkey).GetID();
+ if (!keystore.HaveKey(keyID)) return false;
+ }
+ return true;
}
-isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
+isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, IsMineSigVersion sigversion)
{
isInvalid = false;
@@ -61,7 +63,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
break;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
- if (sigversion != SigVersion::BASE && vSolutions[0].size() != 33) {
+ if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
isInvalid = true;
return ISMINE_NO;
}
@@ -70,20 +72,20 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
break;
case TX_WITNESS_V0_KEYHASH:
{
- if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
+ if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
// We do not support bare witness outputs unless the P2SH version of it would be
// acceptable as well. This protects against matching before segwit activates.
// This also applies to the P2WSH case.
break;
}
- isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SigVersion::WITNESS_V0);
+ isminetype ret = IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, IsMineSigVersion::WITNESS_V0);
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
break;
}
case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
- if (sigversion != SigVersion::BASE) {
+ if (!PermitsUncompressed(sigversion)) {
CPubKey pubkey;
if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
isInvalid = true;
@@ -98,7 +100,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript, isInvalid);
+ isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::P2SH);
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
}
@@ -106,7 +108,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
}
case TX_WITNESS_V0_SCRIPTHASH:
{
- if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
+ if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
break;
}
uint160 hash;
@@ -114,7 +116,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript, isInvalid, SigVersion::WITNESS_V0);
+ isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::WITNESS_V0);
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
}
@@ -123,13 +125,16 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
case TX_MULTISIG:
{
+ // Never treat bare multisig outputs as ours (they can still be made watchonly-though)
+ if (sigversion == IsMineSigVersion::TOP) break;
+
// Only consider transactions "mine" if we own ALL the
// keys involved. Multi-signature transactions that are
// partially owned (somebody else has a key that can spend
// them) enable spend-out-from-under-you attacks, especially
// in shared-wallet situations.
std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
- if (sigversion != SigVersion::BASE) {
+ if (!PermitsUncompressed(sigversion)) {
for (size_t i = 0; i < keys.size(); i++) {
if (keys[i].size() != 33) {
isInvalid = true;
@@ -150,3 +155,22 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool&
}
return ISMINE_NO;
}
+
+} // namespace
+
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid)
+{
+ return IsMineInner(keystore, scriptPubKey, isInvalid, IsMineSigVersion::TOP);
+}
+
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
+{
+ bool isInvalid = false;
+ return IsMine(keystore, scriptPubKey, isInvalid);
+}
+
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest)
+{
+ CScript script = GetScriptForDestination(dest);
+ return IsMine(keystore, script);
+}
diff --git a/src/script/ismine.h b/src/script/ismine.h
index f93a66e35a..8573bdfbd2 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -33,9 +33,8 @@ typedef uint8_t isminefilter;
* different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed
* keys in SigVersion::WITNESS_V0 script, but could also be used in similar cases in the future
*/
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion = SigVersion::BASE);
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion = SigVersion::BASE);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, bool& isInvalid, SigVersion = SigVersion::BASE);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion = SigVersion::BASE);
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid);
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/standard.h b/src/script/standard.h
index 3b2838a5bb..4922b7236b 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -23,7 +23,7 @@ class CScriptID : public uint160
{
public:
CScriptID() : uint160() {}
- CScriptID(const CScript& in);
+ explicit CScriptID(const CScript& in);
CScriptID(const uint160& in) : uint160(in) {}
};
diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index f10fd07c63..a273424b51 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -141,7 +141,7 @@ Arena::Stats Arena::stats() const
}
#ifdef ARENA_DEBUG
-void printchunk(char* base, size_t sz, bool used) {
+static void printchunk(char* base, size_t sz, bool used) {
std::cout <<
"0x" << std::hex << std::setw(16) << std::setfill('0') << base <<
" 0x" << std::hex << std::setw(16) << std::setfill('0') << sz <<
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index abc31e6181..1868aed7dd 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -31,7 +31,7 @@ struct COrphanTx {
};
extern std::map<uint256, COrphanTx> mapOrphanTransactions;
-CService ip(uint32_t i)
+static CService ip(uint32_t i)
{
struct in_addr s;
s.s_addr = i;
@@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
}
-void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
+static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
{
CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
@@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
}
-CTransactionRef RandomOrphan()
+static CTransactionRef RandomOrphan()
{
std::map<uint256, COrphanTx>::iterator it;
LOCK(cs_main);
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
index 21a1153ad0..13ec19834a 100644
--- a/src/test/arith_uint256_tests.cpp
+++ b/src/test/arith_uint256_tests.cpp
@@ -17,7 +17,7 @@
BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup)
/// Convert vector to arith_uint256, via uint256 blob
-inline arith_uint256 arith_uint256V(const std::vector<unsigned char>& vch)
+static inline arith_uint256 arith_uint256V(const std::vector<unsigned char>& vch)
{
return UintToArith256(uint256(vch));
}
@@ -53,7 +53,7 @@ const unsigned char MaxArray[] =
const arith_uint256 MaxL = arith_uint256V(std::vector<unsigned char>(MaxArray,MaxArray+32));
const arith_uint256 HalfL = (OneL << 255);
-std::string ArrayToString(const unsigned char A[], unsigned int width)
+static std::string ArrayToString(const unsigned char A[], unsigned int width)
{
std::stringstream Stream;
Stream << std::hex;
@@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality
tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL);
}
-void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
+static void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
{
for (unsigned int T=0; T < arrayLength; ++T)
{
@@ -136,7 +136,7 @@ void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int
}
}
-void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
+static void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
{
for (unsigned int T=0; T < arrayLength; ++T)
{
@@ -369,7 +369,7 @@ BOOST_AUTO_TEST_CASE( divide )
}
-bool almostEqual(double d1, double d2)
+static bool almostEqual(double d1, double d2)
{
return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits<double>::epsilon();
}
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
index 495290c8d9..c23e23f6a1 100644
--- a/src/test/bech32_tests.cpp
+++ b/src/test/bech32_tests.cpp
@@ -9,7 +9,7 @@
BOOST_FIXTURE_TEST_SUITE(bech32_tests, BasicTestingSetup)
-bool CaseInsensitiveEqual(const std::string &s1, const std::string &s2)
+static bool CaseInsensitiveEqual(const std::string &s1, const std::string &s2)
{
if (s1.size() != s2.size()) return false;
for (size_t i = 0; i < s1.size(); ++i) {
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 3c9ff1877d..51308847f6 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -87,7 +87,7 @@ TestVector test3 =
"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
0);
-void RunTest(const TestVector &test) {
+static void RunTest(const TestVector &test) {
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
CExtKey key;
CExtPubKey pubkey;
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
index 32b408838c..5b8df32158 100644
--- a/src/test/blockchain_tests.cpp
+++ b/src/test/blockchain_tests.cpp
@@ -8,12 +8,12 @@
/* Equality between doubles is imprecise. Comparison should be done
* with a small threshold of tolerance, rather than exact equality.
*/
-bool DoubleEquals(double a, double b, double epsilon)
+static bool DoubleEquals(double a, double b, double epsilon)
{
return std::abs(a - b) < epsilon;
}
-CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
+static CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
{
CBlockIndex* block_index = new CBlockIndex();
block_index->nHeight = 46367;
@@ -22,7 +22,7 @@ CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
return block_index;
}
-CChain CreateChainWithNbits(uint32_t nbits)
+static CChain CreateChainWithNbits(uint32_t nbits)
{
CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits);
CChain chain;
@@ -30,7 +30,7 @@ CChain CreateChainWithNbits(uint32_t nbits)
return chain;
}
-void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
+static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
BOOST_CHECK_MESSAGE(
DoubleEquals(difficulty, expected_difficulty, 0.00001),
"Difficulty was " + std::to_string(difficulty)
@@ -40,7 +40,7 @@ void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
/* Given a BlockIndex with the provided nbits,
* verify that the expected difficulty results.
*/
-void TestDifficulty(uint32_t nbits, double expected_difficulty)
+static void TestDifficulty(uint32_t nbits, double expected_difficulty)
{
CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits);
/* Since we are passing in block index explicitly,
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index de47216449..c8de7f4a7c 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -146,7 +146,7 @@ typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue;
/** This test case checks that the CCheckQueue works properly
* with each specified size_t Checks pushed.
*/
-void Correct_Queue_range(std::vector<size_t> range)
+static void Correct_Queue_range(std::vector<size_t> range)
{
auto small_queue = std::unique_ptr<Correct_Queue>(new Correct_Queue {QUEUE_BATCH_SIZE});
boost::thread_group tg;
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index a146c69fd2..276d5b80ee 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -540,7 +540,7 @@ const static auto FLAGS = {char(0), FRESH, DIRTY, char(DIRTY | FRESH)};
const static auto CLEAN_FLAGS = {char(0), FRESH};
const static auto ABSENT_FLAGS = {NO_ENTRY};
-void SetCoinsValue(CAmount value, Coin& coin)
+static void SetCoinsValue(CAmount value, Coin& coin)
{
assert(value != ABSENT);
coin.Clear();
@@ -552,7 +552,7 @@ void SetCoinsValue(CAmount value, Coin& coin)
}
}
-size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
+static size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
{
if (value == ABSENT) {
assert(flags == NO_ENTRY);
@@ -605,7 +605,7 @@ public:
CCoinsViewCacheTest cache{&base};
};
-void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
+static void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
{
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
test.cache.AccessCoin(OUTPOINT);
@@ -656,7 +656,7 @@ BOOST_AUTO_TEST_CASE(ccoins_access)
CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
}
-void CheckSpendCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
+static void CheckSpendCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
{
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
test.cache.SpendCoin(OUTPOINT);
@@ -707,7 +707,7 @@ BOOST_AUTO_TEST_CASE(ccoins_spend)
CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
}
-void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase)
+static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase)
{
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
@@ -734,7 +734,7 @@ void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_va
// while still verifying that the CoinsViewCache::AddCoin implementation
// ignores base values.
template <typename... Args>
-void CheckAddCoin(Args&&... args)
+static void CheckAddCoin(Args&&... args)
{
for (CAmount base_value : {ABSENT, PRUNED, VALUE1})
CheckAddCoinBase(base_value, std::forward<Args>(args)...);
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index de0d72614b..518cb849bb 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -23,7 +23,7 @@
BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup)
template<typename Hasher, typename In, typename Out>
-void TestVector(const Hasher &h, const In &in, const Out &out) {
+static void TestVector(const Hasher &h, const In &in, const Out &out) {
Out hash;
BOOST_CHECK(out.size() == h.OUTPUT_SIZE);
hash.resize(out.size());
@@ -51,22 +51,22 @@ void TestVector(const Hasher &h, const In &in, const Out &out) {
}
}
-void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));}
-void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));}
-void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));}
-void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));}
+static void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));}
+static void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));}
+static void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));}
+static void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));}
-void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+static void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
std::vector<unsigned char> key = ParseHex(hexkey);
TestVector(CHMAC_SHA256(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
}
-void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+static void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
std::vector<unsigned char> key = ParseHex(hexkey);
TestVector(CHMAC_SHA512(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
}
-void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
+static void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> in = ParseHex(hexin);
@@ -86,7 +86,7 @@ void TestAES128(const std::string &hexkey, const std::string &hexin, const std::
BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in));
}
-void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
+static void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> in = ParseHex(hexin);
@@ -105,7 +105,7 @@ void TestAES256(const std::string &hexkey, const std::string &hexin, const std::
BOOST_CHECK(buf == in);
}
-void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
+static void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> iv = ParseHex(hexiv);
@@ -146,7 +146,7 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad
}
}
-void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
+static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> iv = ParseHex(hexiv);
@@ -187,7 +187,7 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad
}
}
-void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
+static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
ChaCha20 rng(key.data(), key.size());
@@ -200,7 +200,7 @@ void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, cons
BOOST_CHECK(out == outres);
}
-std::string LongTestString(void) {
+static std::string LongTestString(void) {
std::string ret;
for (int i=0; i<200000; i++) {
ret += (unsigned char)(i);
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index ccd5caacd5..857ab8a1b7 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
/** insecure_GetRandHash fills in a uint256 from local_rand_ctx
*/
-void insecure_GetRandHash(uint256& t)
+static void insecure_GetRandHash(uint256& t)
{
uint32_t* ptr = (uint32_t*)t.begin();
for (uint8_t j = 0; j < 8; ++j)
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
* inserted into a megabytes sized cache
*/
template <typename Cache>
-double test_cache(size_t megabytes, double load)
+static double test_cache(size_t megabytes, double load)
{
local_rand_ctx = FastRandomContext(true);
std::vector<uint256> hashes;
@@ -109,7 +109,7 @@ double test_cache(size_t megabytes, double load)
* how you measure around load 1.0 as after load 1.0 your normalized hit rate
* becomes effectively perfect, ignoring freshness.
*/
-double normalize_hit_rate(double hits, double load)
+static double normalize_hit_rate(double hits, double load)
{
return hits * std::max(load, 1.0);
}
@@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok)
/** This helper checks that erased elements are preferentially inserted onto and
* that the hit rate of "fresher" keys is reasonable*/
template <typename Cache>
-void test_cache_erase(size_t megabytes)
+static void test_cache_erase(size_t megabytes)
{
double load = 1;
local_rand_ctx = FastRandomContext(true);
@@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(cuckoocache_erase_ok)
}
template <typename Cache>
-void test_cache_erase_parallel(size_t megabytes)
+static void test_cache_erase_parallel(size_t megabytes)
{
double load = 1;
local_rand_ctx = FastRandomContext(true);
@@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(cuckoocache_erase_parallel_ok)
template <typename Cache>
-void test_cache_generations()
+static void test_cache_generations()
{
// This test checks that for a simulation of network activity, the fresh hit
// rate is never below 99%, and the number of times that it is worse than
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index edc41ec42c..6df5aec9c9 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -12,7 +12,7 @@
#include <boost/test/unit_test.hpp>
// Test if a string consists entirely of null characters
-bool is_null_key(const std::vector<unsigned char>& key) {
+static bool is_null_key(const std::vector<unsigned char>& key) {
bool isnull = true;
for (unsigned int i = 0; i < key.size(); i++)
diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp
index 570c205731..8676a099da 100644
--- a/src/test/main_tests.cpp
+++ b/src/test/main_tests.cpp
@@ -58,8 +58,8 @@ BOOST_AUTO_TEST_CASE(subsidy_limit_test)
BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000});
}
-bool ReturnFalse() { return false; }
-bool ReturnTrue() { return true; }
+static bool ReturnFalse() { return false; }
+static bool ReturnTrue() { return true; }
BOOST_AUTO_TEST_CASE(test_combiner_all)
{
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 37615d08b3..c4b18151a7 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
}
template<typename name>
-void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
+static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
{
BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
typename CTxMemPool::indexed_transaction_set::index<name>::type::iterator it = pool.mapTx.get<name>().begin();
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index c98566f9ca..9a325f5f4c 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -82,7 +82,7 @@ struct {
{2, 0xbbbeb305}, {2, 0xfe1c810a},
};
-CBlockIndex CreateBlockIndex(int nHeight)
+static CBlockIndex CreateBlockIndex(int nHeight)
{
CBlockIndex index;
index.nHeight = nHeight;
@@ -90,7 +90,7 @@ CBlockIndex CreateBlockIndex(int nHeight)
return index;
}
-bool TestSequenceLocks(const CTransaction &tx, int flags)
+static bool TestSequenceLocks(const CTransaction &tx, int flags)
{
LOCK(mempool.cs);
return CheckSequenceLocks(tx, flags);
@@ -99,7 +99,7 @@ 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.
-void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
+static void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 066f6328a6..77db9f5c57 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -18,7 +18,7 @@
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
-CScript
+static CScript
sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction, int whichIn)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE);
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 436ae696d1..42e615ab0c 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -63,7 +63,7 @@ public:
}
};
-CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
+static CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
{
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
ssPeersIn << Params().MessageStart();
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index 767c5fdbd2..ff0bf6c66d 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -561,7 +561,14 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
keystore.AddKey(keys[1]);
result = IsMine(keystore, scriptPubKey, isInvalid);
- BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+
+ // Keystore has 2/2 keys and the script
+ keystore.AddCScript(scriptPubKey);
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
BOOST_CHECK(!isInvalid);
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 068f1e66f4..f561660fef 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -99,7 +99,7 @@ static ScriptErrorDesc script_errors[]={
{SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"},
};
-const char *FormatScriptError(ScriptError_t err)
+static const char *FormatScriptError(ScriptError_t err)
{
for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
if (script_errors[i].err == err)
@@ -108,7 +108,7 @@ const char *FormatScriptError(ScriptError_t err)
return "";
}
-ScriptError_t ParseScriptError(const std::string &name)
+static ScriptError_t ParseScriptError(const std::string &name)
{
for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
if (script_errors[i].name == name)
@@ -1028,7 +1028,7 @@ BOOST_AUTO_TEST_CASE(script_PushData)
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
-CScript
+static CScript
sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction)
{
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SigVersion::BASE);
@@ -1052,7 +1052,7 @@ sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const
}
return result;
}
-CScript
+static CScript
sign_multisig(const CScript& scriptPubKey, const CKey& key, const CTransaction& transaction)
{
std::vector<CKey> keys;
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index b4d8a2419e..86647e72eb 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
* Verifies script execution of the zeroth scriptPubKey of tx output and
* zeroth scriptSig and witness of tx input.
*/
-ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags)
+static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags)
{
ScriptError error;
CTransaction inputi(input);
@@ -82,7 +82,7 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction
* and witness such that spendingTx spends output zero of creationTx.
* Also inserts creationTx's output into the coins view.
*/
-void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& witness)
+static void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& witness)
{
creationTx.nVersion = 1;
creationTx.vin.resize(1);
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index e9873f4526..fe816a6f79 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -47,7 +47,6 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
SetupNetworking();
InitSignatureCache();
InitScriptExecutionCache();
- fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
SelectParams(chainName);
noui_connect();
diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp
index 69e9804c2f..b2daa2adb5 100644
--- a/src/test/test_bitcoin_fuzzy.cpp
+++ b/src/test/test_bitcoin_fuzzy.cpp
@@ -52,7 +52,7 @@ enum TEST_ID {
TEST_ID_END
};
-bool read_stdin(std::vector<uint8_t> &data) {
+static bool read_stdin(std::vector<uint8_t> &data) {
uint8_t buffer[1024];
ssize_t length=0;
while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
@@ -63,7 +63,7 @@ bool read_stdin(std::vector<uint8_t> &data) {
return length==0;
}
-int test_one_input(std::vector<uint8_t> buffer) {
+static int test_one_input(std::vector<uint8_t> buffer) {
if (buffer.size() < sizeof(uint32_t)) return 0;
uint32_t test_id = 0xffffffff;
diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp
index 9ece9e70c2..8bd5ce1222 100644
--- a/src/test/torcontrol_tests.cpp
+++ b/src/test/torcontrol_tests.cpp
@@ -10,7 +10,7 @@
BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
-void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
+static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
{
BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")");
auto ret = SplitTorReplyLine(input);
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", " EVEN+more ARGS");
}
-void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
+static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
{
BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")");
auto ret = ParseTorReplyMapping(input);
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index b222392ee5..c753e0a11d 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(test_Get)
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
}
-void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true)
+static void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true)
{
CMutableTransaction outputm;
outputm.nVersion = 1;
@@ -381,7 +381,7 @@ void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, C
assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack);
}
-void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, int flags, bool success)
+static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, int flags, bool success)
{
ScriptError error;
CTransaction inputi(input);
@@ -404,7 +404,7 @@ static CScript PushAll(const std::vector<valtype>& values)
return result;
}
-void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
+static void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
{
std::vector<valtype> stack;
EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 7a52697859..eb23ba5ad2 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -102,7 +102,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// should fail.
// Capture this interaction with the upgraded_nop argument: set it when evaluating
// any script flag that is implemented as an upgraded NOP code.
-void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache)
+static void ValidateCheckInputsForAllFlags(CMutableTransaction &tx, uint32_t failing_flags, bool add_to_cache)
{
PrecomputedTransactionData txdata(tx);
// If we add many more flags, this loop can get too expensive, but we can
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index 20ed29f59b..79217fa430 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -48,7 +48,7 @@ const unsigned char MaxArray[] =
const uint256 MaxL = uint256(std::vector<unsigned char>(MaxArray,MaxArray+32));
const uint160 MaxS = uint160(std::vector<unsigned char>(MaxArray,MaxArray+20));
-std::string ArrayToString(const unsigned char A[], unsigned int width)
+static std::string ArrayToString(const unsigned char A[], unsigned int width)
{
std::stringstream Stream;
Stream << std::hex;
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 92ef58e517..7442825300 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -12,7 +12,7 @@
#include <boost/test/unit_test.hpp>
/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
-int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
+static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
static const Consensus::Params paramsDummy = Consensus::Params();
diff --git a/src/timedata.cpp b/src/timedata.cpp
index a803b2fc87..27d08172f5 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -110,9 +110,9 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
if (LogAcceptCategory(BCLog::NET)) {
for (int64_t n : vSorted) {
- LogPrint(BCLog::NET, "%+d ", n);
+ LogPrint(BCLog::NET, "%+d ", n); /* Continued */
}
- LogPrint(BCLog::NET, "| ");
+ LogPrint(BCLog::NET, "| "); /* Continued */
LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
}
diff --git a/src/txmempool.h b/src/txmempool.h
index a1cde6f779..3f9fb4850c 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -451,7 +451,7 @@ private:
mutable bool blockSinceLastRollingFeeBump;
mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
- void trackPackageRemoved(const CFeeRate& rate);
+ void trackPackageRemoved(const CFeeRate& rate) EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
@@ -512,7 +512,7 @@ private:
void UpdateParent(txiter entry, txiter parent, bool add);
void UpdateChild(txiter entry, txiter child, bool add);
- std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const;
+ std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx;
@@ -572,7 +572,7 @@ public:
* Set updateDescendants to true when removing a tx that was in a block, so
* that any in-mempool descendants have their ancestor state updated.
*/
- void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
+ void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN) EXCLUSIVE_LOCKS_REQUIRED(cs);
/** When adding transactions from a disconnected block back to the mempool,
* new mempool entries may have children in the mempool (which is generally
diff --git a/src/util.cpp b/src/util.cpp
index 9a3067259f..b4d0a61ab2 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -887,7 +887,9 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
// Fallback version
// TODO: just write one byte per block
static const char buf[65536] = {};
- fseek(file, offset, SEEK_SET);
+ if (fseek(file, offset, SEEK_SET)) {
+ return;
+ }
while (length > 0) {
unsigned int now = 65536;
if (length < now)
diff --git a/src/util.h b/src/util.h
index ce94f396af..2da8023285 100644
--- a/src/util.h
+++ b/src/util.h
@@ -66,7 +66,7 @@ bool SetupNetworking();
template<typename... Args>
bool error(const char* fmt, const Args&... args)
{
- LogPrintStr("ERROR: " + tfm::format(fmt, args...) + "\n");
+ LogPrintf("ERROR: %s\n", tfm::format(fmt, args...));
return false;
}
diff --git a/src/validation.cpp b/src/validation.cpp
index 14257d78f9..fc1f6477d5 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -477,7 +477,7 @@ static bool IsCurrentForFeeEstimation()
* and instead just erase from the mempool as needed.
*/
-void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool)
+static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool)
{
AssertLockHeld(cs_main);
std::vector<uint256> vHashUpdate;
@@ -1487,7 +1487,7 @@ static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex)
}
/** Abort with a message */
-bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
+static bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
{
SetMiscWarning(strMessage);
LogPrintf("*** %s\n", strMessage);
@@ -1498,7 +1498,7 @@ bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
return false;
}
-bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="")
+static bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage="")
{
AbortNode(strMessage, userMessage);
return state.Error(strMessage);
@@ -2066,13 +2066,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
LOCK(cs_main);
static int64_t nLastWrite = 0;
static int64_t nLastFlush = 0;
- static int64_t nLastSetChain = 0;
std::set<int> setFilesToPrune;
- bool fFlushForPrune = false;
- bool fDoFullFlush = false;
- int64_t nNow = 0;
+ bool full_flush_completed = false;
try {
{
+ bool fFlushForPrune = false;
+ bool fDoFullFlush = false;
LOCK(cs_LastBlockFile);
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) {
if (nManualPruneHeight > 0) {
@@ -2089,7 +2088,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
}
}
}
- nNow = GetTimeMicros();
+ int64_t nNow = GetTimeMicros();
// Avoid writing/flushing immediately after startup.
if (nLastWrite == 0) {
nLastWrite = nNow;
@@ -2097,9 +2096,6 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
if (nLastFlush == 0) {
nLastFlush = nNow;
}
- if (nLastSetChain == 0) {
- nLastSetChain = nNow;
- }
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
int64_t cacheSize = pcoinsTip->DynamicMemoryUsage();
int64_t nTotalSpace = nCoinCacheUsage + std::max<int64_t>(nMempoolSizeMax - nMempoolUsage, 0);
@@ -2156,12 +2152,12 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
if (!pcoinsTip->Flush())
return AbortNode(state, "Failed to write to coin database");
nLastFlush = nNow;
+ full_flush_completed = true;
}
}
- if (fDoFullFlush || ((mode == FlushStateMode::ALWAYS || mode == FlushStateMode::PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
+ if (full_flush_completed) {
// Update best block in wallet (so we can detect restored wallets).
- GetMainSignals().SetBestChain(chainActive.GetLocator());
- nLastSetChain = nNow;
+ GetMainSignals().ChainStateFlushed(chainActive.GetLocator());
}
} catch (const std::runtime_error& e) {
return AbortNode(state, std::string("System error while flushing: ") + e.what());
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 746263f113..f328d2d14b 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -25,7 +25,7 @@ struct MainSignalsInstance {
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
- boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
+ boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
boost::signals2::signal<void (const uint256 &)> Inventory;
boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
@@ -80,7 +80,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
- g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
+ g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
@@ -91,7 +91,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
- g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
+ g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
@@ -107,7 +107,7 @@ void UnregisterAllValidationInterfaces() {
g_signals.m_internals->BlockChecked.disconnect_all_slots();
g_signals.m_internals->Broadcast.disconnect_all_slots();
g_signals.m_internals->Inventory.disconnect_all_slots();
- g_signals.m_internals->SetBestChain.disconnect_all_slots();
+ g_signals.m_internals->ChainStateFlushed.disconnect_all_slots();
g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
g_signals.m_internals->BlockConnected.disconnect_all_slots();
g_signals.m_internals->BlockDisconnected.disconnect_all_slots();
@@ -166,9 +166,9 @@ void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock
});
}
-void CMainSignals::SetBestChain(const CBlockLocator &locator) {
+void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
m_internals->m_schedulerClient.AddToProcessQueue([locator, this] {
- m_internals->SetBestChain(locator);
+ m_internals->ChainStateFlushed(locator);
});
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 63097166af..3a5fed0106 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -99,9 +99,20 @@ protected:
/**
* Notifies listeners of the new active block chain on-disk.
*
+ * Prior to this callback, any updates are not guaranteed to persist on disk
+ * (ie clients need to handle shutdown/restart safety by being able to
+ * understand when some updates were lost due to unclean shutdown).
+ *
+ * When this callback is invoked, the validation changes done by any prior
+ * callback are guaranteed to exist on disk and survive a restart, including
+ * an unclean shutdown.
+ *
+ * Provides a locator describing the best chain, which is likely useful for
+ * storing current state on disk in client DBs.
+ *
* Called on a background thread.
*/
- virtual void SetBestChain(const CBlockLocator &locator) {}
+ virtual void ChainStateFlushed(const CBlockLocator &locator) {}
/**
* Notifies listeners about an inventory item being seen on the network.
*
@@ -157,7 +168,7 @@ public:
void TransactionAddedToMempool(const CTransactionRef &);
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
- void SetBestChain(const CBlockLocator &);
+ void ChainStateFlushed(const CBlockLocator &);
void Inventory(const uint256 &);
void Broadcast(int64_t nBestBlockTime, CConnman* connman);
void BlockChecked(const CBlock&, const CValidationState&);
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 8596ad2adc..a403411e5b 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -286,10 +286,10 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<CInputCoin>& vCoins
}
if (LogAcceptCategory(BCLog::SELECTCOINS)) {
- LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: ");
+ LogPrint(BCLog::SELECTCOINS, "SelectCoins() best subset: "); /* Continued */
for (unsigned int i = 0; i < vValue.size(); i++) {
if (vfBest[i]) {
- LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].txout.nValue));
+ LogPrint(BCLog::SELECTCOINS, "%s ", FormatMoney(vValue[i].txout.nValue)); /* Continued */
}
}
LogPrint(BCLog::SELECTCOINS, "total %s\n", FormatMoney(nBest));
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index b8533839a0..e957c1b1ca 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -4,7 +4,6 @@
#include <chain.h>
#include <key_io.h>
-#include <rpc/safemode.h>
#include <rpc/server.h>
#include <validation.h>
#include <script/script.h>
@@ -52,7 +51,7 @@ std::string static EncodeDumpString(const std::string &str) {
return ret.str();
}
-std::string DecodeDumpString(const std::string &str) {
+static std::string DecodeDumpString(const std::string &str) {
std::stringstream ret;
for (unsigned int pos = 0; pos < str.length(); pos++) {
unsigned char c = str[pos];
@@ -66,7 +65,7 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}
-bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
+static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
{
bool fLabelFound = false;
CKey key;
@@ -204,14 +203,13 @@ UniValue abortrescan(const JSONRPCRequest& request)
+ HelpExampleRpc("abortrescan", "")
);
- ObserveSafeMode();
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan();
return true;
}
-void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
-void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
+static void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
+static void ImportScript(CWallet* const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
{
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -224,10 +222,11 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri
}
if (isRedeemScript) {
- if (!pwallet->HaveCScript(script) && !pwallet->AddCScript(script)) {
+ const CScriptID id(script);
+ if (!pwallet->HaveCScript(id) && !pwallet->AddCScript(script)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- ImportAddress(pwallet, CScriptID(script), strLabel);
+ ImportAddress(pwallet, id, strLabel);
} else {
CTxDestination destination;
if (ExtractDestination(script, destination)) {
@@ -236,7 +235,7 @@ void ImportScript(CWallet* const pwallet, const CScript& script, const std::stri
}
}
-void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel)
+static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, const std::string& strLabel)
{
CScript script = GetScriptForDestination(dest);
ImportScript(pwallet, script, strLabel, false);
@@ -602,7 +601,8 @@ UniValue importwallet(const JSONRPCRequest& request)
} else if(IsHex(vstr[0])) {
std::vector<unsigned char> vData(ParseHex(vstr[0]));
CScript script = CScript(vData.begin(), vData.end());
- if (pwallet->HaveCScript(script)) {
+ CScriptID id(script);
+ if (pwallet->HaveCScript(id)) {
LogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
continue;
}
@@ -613,7 +613,7 @@ UniValue importwallet(const JSONRPCRequest& request)
}
int64_t birth_time = DecodeDumpTime(vstr[1]);
if (birth_time > 0) {
- pwallet->m_script_metadata[CScriptID(script)].nCreateTime = birth_time;
+ pwallet->m_script_metadata[id].nCreateTime = birth_time;
nTimeBegin = std::min(nTimeBegin, birth_time);
}
}
@@ -811,7 +811,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
}
-UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
+static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
{
try {
bool success = false;
@@ -899,12 +899,12 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- if (!pwallet->HaveCScript(redeemScript) && !pwallet->AddCScript(redeemScript)) {
+ CScriptID redeem_id(redeemScript);
+ if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
}
- CTxDestination redeem_dest = CScriptID(redeemScript);
- CScript redeemDestination = GetScriptForDestination(redeem_dest);
+ CScript redeemDestination = GetScriptForDestination(redeem_id);
if (::IsMine(*pwallet, redeemDestination) == ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
@@ -1111,7 +1111,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
}
}
-int64_t GetImportTimestamp(const UniValue& data, int64_t now)
+static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
{
if (data.exists("timestamp")) {
const UniValue& timestamp = data["timestamp"];
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index c4c6701081..94e61aa20e 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -17,7 +17,6 @@
#include <policy/rbf.h>
#include <rpc/mining.h>
#include <rpc/rawtransaction.h>
-#include <rpc/safemode.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/sign.h>
@@ -86,7 +85,7 @@ void EnsureWalletIsUnlocked(CWallet * const pwallet)
}
}
-void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
+static void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain();
entry.pushKV("confirmations", confirms);
@@ -125,7 +124,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
entry.pushKV(item.first, item.second);
}
-std::string LabelFromValue(const UniValue& value)
+static std::string LabelFromValue(const UniValue& value)
{
std::string label = value.get_str();
if (label == "*")
@@ -133,7 +132,7 @@ std::string LabelFromValue(const UniValue& value)
return label;
}
-UniValue getnewaddress(const JSONRPCRequest& request)
+static UniValue getnewaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -165,8 +164,7 @@ UniValue getnewaddress(const JSONRPCRequest& request)
OutputType output_type = pwallet->m_default_address_type;
if (!request.params[1].isNull()) {
- output_type = ParseOutputType(request.params[1].get_str(), pwallet->m_default_address_type);
- if (output_type == OutputType::NONE) {
+ if (!ParseOutputType(request.params[1].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
}
}
@@ -198,7 +196,7 @@ CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& la
return dest;
}
-UniValue getlabeladdress(const JSONRPCRequest& request)
+static UniValue getlabeladdress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -256,7 +254,7 @@ UniValue getlabeladdress(const JSONRPCRequest& request)
}
-UniValue getrawchangeaddress(const JSONRPCRequest& request)
+static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -283,10 +281,9 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
}
- OutputType output_type = pwallet->m_default_change_type != OutputType::NONE ? pwallet->m_default_change_type : pwallet->m_default_address_type;
+ OutputType output_type = pwallet->m_default_change_type != OutputType::CHANGE_AUTO ? pwallet->m_default_change_type : pwallet->m_default_address_type;
if (!request.params[0].isNull()) {
- output_type = ParseOutputType(request.params[0].get_str(), output_type);
- if (output_type == OutputType::NONE) {
+ if (!ParseOutputType(request.params[0].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
}
}
@@ -305,7 +302,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
}
-UniValue setlabel(const JSONRPCRequest& request)
+static UniValue setlabel(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -359,7 +356,7 @@ UniValue setlabel(const JSONRPCRequest& request)
}
-UniValue getaccount(const JSONRPCRequest& request)
+static UniValue getaccount(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -402,7 +399,7 @@ UniValue getaccount(const JSONRPCRequest& request)
}
-UniValue getaddressesbyaccount(const JSONRPCRequest& request)
+static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -488,7 +485,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
return tx;
}
-UniValue sendtoaddress(const JSONRPCRequest& request)
+static UniValue sendtoaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -525,8 +522,6 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -577,7 +572,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
return tx->GetHash().GetHex();
}
-UniValue listaddressgroupings(const JSONRPCRequest& request)
+static UniValue listaddressgroupings(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -607,8 +602,6 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
+ HelpExampleRpc("listaddressgroupings", "")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -636,7 +629,7 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
return jsonGroupings;
}
-UniValue signmessage(const JSONRPCRequest& request)
+static UniValue signmessage(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -697,7 +690,7 @@ UniValue signmessage(const JSONRPCRequest& request)
return EncodeBase64(vchSig.data(), vchSig.size());
}
-UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -724,8 +717,6 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -764,7 +755,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
}
-UniValue getreceivedbylabel(const JSONRPCRequest& request)
+static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -798,8 +789,6 @@ UniValue getreceivedbylabel(const JSONRPCRequest& request)
+ HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -836,7 +825,7 @@ UniValue getreceivedbylabel(const JSONRPCRequest& request)
}
-UniValue getbalance(const JSONRPCRequest& request)
+static UniValue getbalance(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -879,8 +868,6 @@ UniValue getbalance(const JSONRPCRequest& request)
+ HelpExampleRpc("getbalance", "\"*\", 6")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -921,7 +908,7 @@ UniValue getbalance(const JSONRPCRequest& request)
return ValueFromAmount(pwallet->GetBalance());
}
-UniValue getunconfirmedbalance(const JSONRPCRequest &request)
+static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -933,8 +920,6 @@ UniValue getunconfirmedbalance(const JSONRPCRequest &request)
"getunconfirmedbalance\n"
"Returns the server's total unconfirmed balance\n");
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -945,7 +930,7 @@ UniValue getunconfirmedbalance(const JSONRPCRequest &request)
}
-UniValue movecmd(const JSONRPCRequest& request)
+static UniValue movecmd(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -980,7 +965,6 @@ UniValue movecmd(const JSONRPCRequest& request)
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
);
- ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::string strFrom = LabelFromValue(request.params[0]);
@@ -1003,7 +987,7 @@ UniValue movecmd(const JSONRPCRequest& request)
}
-UniValue sendfrom(const JSONRPCRequest& request)
+static UniValue sendfrom(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1039,8 +1023,6 @@ UniValue sendfrom(const JSONRPCRequest& request)
+ HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -1078,7 +1060,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
}
-UniValue sendmany(const JSONRPCRequest& request)
+static UniValue sendmany(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1170,8 +1152,6 @@ UniValue sendmany(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error(help_text);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -1275,7 +1255,7 @@ UniValue sendmany(const JSONRPCRequest& request)
return tx->GetHash().GetHex();
}
-UniValue addmultisigaddress(const JSONRPCRequest& request)
+static UniValue addmultisigaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1335,8 +1315,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
OutputType output_type = pwallet->m_default_address_type;
if (!request.params[3].isNull()) {
- output_type = ParseOutputType(request.params[3].get_str(), output_type);
- if (output_type == OutputType::NONE) {
+ if (!ParseOutputType(request.params[3].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
}
}
@@ -1411,7 +1390,7 @@ public:
bool operator()(const T& dest) { return false; }
};
-UniValue addwitnessaddress(const JSONRPCRequest& request)
+static UniValue addwitnessaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1497,7 +1476,7 @@ struct tallyitem
}
};
-UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label)
+static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label)
{
// Minimum confirmations
int nMinDepth = 1;
@@ -1643,7 +1622,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_l
return ret;
}
-UniValue listreceivedbyaddress(const JSONRPCRequest& request)
+static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1683,8 +1662,6 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -1694,7 +1671,7 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
return ListReceived(pwallet, request.params, false);
}
-UniValue listreceivedbylabel(const JSONRPCRequest& request)
+static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -1735,8 +1712,6 @@ UniValue listreceivedbylabel(const JSONRPCRequest& request)
+ HelpExampleRpc("listreceivedbylabel", "6, true, true")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -1764,7 +1739,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
* @param ret The UniValue into which the result is stored.
* @param filter The "is mine" filter bool.
*/
-void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
+static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
{
CAmount nFee;
std::string strSentAccount;
@@ -1844,7 +1819,7 @@ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::s
}
}
-void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccount, UniValue& ret)
+static void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccount, UniValue& ret)
{
bool fAllAccounts = (strAccount == std::string("*"));
@@ -1974,8 +1949,6 @@ UniValue listtransactions(const JSONRPCRequest& request)
}
if (request.fHelp || request.params.size() > 4) throw std::runtime_error(help_text);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -2051,7 +2024,7 @@ UniValue listtransactions(const JSONRPCRequest& request)
return ret;
}
-UniValue listaccounts(const JSONRPCRequest& request)
+static UniValue listaccounts(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2088,8 +2061,6 @@ UniValue listaccounts(const JSONRPCRequest& request)
+ HelpExampleRpc("listaccounts", "6")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -2146,7 +2117,7 @@ UniValue listaccounts(const JSONRPCRequest& request)
return ret;
}
-UniValue listsinceblock(const JSONRPCRequest& request)
+static UniValue listsinceblock(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2202,8 +2173,6 @@ UniValue listsinceblock(const JSONRPCRequest& request)
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -2287,7 +2256,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
return ret;
}
-UniValue gettransaction(const JSONRPCRequest& request)
+static UniValue gettransaction(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2339,8 +2308,6 @@ UniValue gettransaction(const JSONRPCRequest& request)
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -2383,7 +2350,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
return entry;
}
-UniValue abandontransaction(const JSONRPCRequest& request)
+static UniValue abandontransaction(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2407,8 +2374,6 @@ UniValue abandontransaction(const JSONRPCRequest& request)
);
}
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -2429,7 +2394,7 @@ UniValue abandontransaction(const JSONRPCRequest& request)
}
-UniValue backupwallet(const JSONRPCRequest& request)
+static UniValue backupwallet(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2462,7 +2427,7 @@ UniValue backupwallet(const JSONRPCRequest& request)
}
-UniValue keypoolrefill(const JSONRPCRequest& request)
+static UniValue keypoolrefill(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2509,7 +2474,7 @@ static void LockWallet(CWallet* pWallet)
pWallet->Lock();
}
-UniValue walletpassphrase(const JSONRPCRequest& request)
+static UniValue walletpassphrase(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2582,7 +2547,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
}
-UniValue walletpassphrasechange(const JSONRPCRequest& request)
+static UniValue walletpassphrasechange(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2631,7 +2596,7 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request)
}
-UniValue walletlock(const JSONRPCRequest& request)
+static UniValue walletlock(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2669,7 +2634,7 @@ UniValue walletlock(const JSONRPCRequest& request)
}
-UniValue encryptwallet(const JSONRPCRequest& request)
+static UniValue encryptwallet(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2729,7 +2694,7 @@ UniValue encryptwallet(const JSONRPCRequest& request)
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
}
-UniValue lockunspent(const JSONRPCRequest& request)
+static UniValue lockunspent(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2856,7 +2821,7 @@ UniValue lockunspent(const JSONRPCRequest& request)
return true;
}
-UniValue listlockunspent(const JSONRPCRequest& request)
+static UniValue listlockunspent(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2889,7 +2854,6 @@ UniValue listlockunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listlockunspent", "")
);
- ObserveSafeMode();
LOCK2(cs_main, pwallet->cs_wallet);
std::vector<COutPoint> vOutpts;
@@ -2908,7 +2872,7 @@ UniValue listlockunspent(const JSONRPCRequest& request)
return ret;
}
-UniValue settxfee(const JSONRPCRequest& request)
+static UniValue settxfee(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2937,7 +2901,7 @@ UniValue settxfee(const JSONRPCRequest& request)
return true;
}
-UniValue getwalletinfo(const JSONRPCRequest& request)
+static UniValue getwalletinfo(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -2968,8 +2932,6 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
+ HelpExampleRpc("getwalletinfo", "")
);
- ObserveSafeMode();
-
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -3000,7 +2962,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request)
return obj;
}
-UniValue listwallets(const JSONRPCRequest& request)
+static UniValue listwallets(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -3032,7 +2994,7 @@ UniValue listwallets(const JSONRPCRequest& request)
return obj;
}
-UniValue resendwallettransactions(const JSONRPCRequest& request)
+static UniValue resendwallettransactions(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -3067,7 +3029,7 @@ UniValue resendwallettransactions(const JSONRPCRequest& request)
return result;
}
-UniValue listunspent(const JSONRPCRequest& request)
+static UniValue listunspent(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -3126,8 +3088,6 @@ UniValue listunspent(const JSONRPCRequest& request)
+ HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ")
);
- ObserveSafeMode();
-
int nMinDepth = 1;
if (!request.params[0].isNull()) {
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
@@ -3189,9 +3149,13 @@ UniValue listunspent(const JSONRPCRequest& request)
UniValue results(UniValue::VARR);
std::vector<COutput> vecOutputs;
- LOCK2(cs_main, pwallet->cs_wallet);
+ {
+ LOCK2(cs_main, pwallet->cs_wallet);
+ pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
+ }
+
+ LOCK(pwallet->cs_wallet);
- pwallet->AvailableCoins(vecOutputs, !include_unsafe, nullptr, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth);
for (const COutput& out : vecOutputs) {
CTxDestination address;
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
@@ -3207,10 +3171,11 @@ UniValue listunspent(const JSONRPCRequest& request)
if (fValidAddress) {
entry.pushKV("address", EncodeDestination(address));
- if (pwallet->mapAddressBook.count(address)) {
- entry.pushKV("label", pwallet->mapAddressBook[address].name);
+ auto i = pwallet->mapAddressBook.find(address);
+ if (i != pwallet->mapAddressBook.end()) {
+ entry.pushKV("label", i->second.name);
if (IsDeprecatedRPCEnabled("accounts")) {
- entry.pushKV("account", pwallet->mapAddressBook[address].name);
+ entry.pushKV("account", i->second.name);
}
}
@@ -3235,7 +3200,7 @@ UniValue listunspent(const JSONRPCRequest& request)
return results;
}
-UniValue fundrawtransaction(const JSONRPCRequest& request)
+static UniValue fundrawtransaction(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -3300,7 +3265,6 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- ObserveSafeMode();
RPCTypeCheck(request.params, {UniValue::VSTR});
// Make sure the results are valid at least up to the most recent block
@@ -3355,8 +3319,8 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists("changeAddress")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options");
}
- coinControl.m_change_type = ParseOutputType(options["change_type"].get_str(), pwallet->m_default_change_type);
- if (coinControl.m_change_type == OutputType::NONE) {
+ coinControl.m_change_type = pwallet->m_default_change_type;
+ if (!ParseOutputType(options["change_type"].get_str(), *coinControl.m_change_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str()));
}
}
@@ -3505,7 +3469,7 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]);
}
-UniValue bumpfee(const JSONRPCRequest& request)
+static UniValue bumpfee(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
@@ -3884,7 +3848,7 @@ public:
UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }
};
-UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest)
+static UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& dest)
{
UniValue ret(UniValue::VOBJ);
UniValue detail = DescribeAddress(dest);
@@ -4020,7 +3984,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
return ret;
}
-UniValue getaddressesbylabel(const JSONRPCRequest& request)
+static UniValue getaddressesbylabel(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
@@ -4063,7 +4027,7 @@ UniValue getaddressesbylabel(const JSONRPCRequest& request)
return ret;
}
-UniValue listlabels(const JSONRPCRequest& request)
+static UniValue listlabels(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ad3dd4cd2c..96242c6b13 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -11,6 +11,7 @@
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <fs.h>
+#include <init.h>
#include <key.h>
#include <key_io.h>
#include <keystore.h>
@@ -34,10 +35,12 @@
#include <boost/algorithm/string/replace.hpp>
-static std::vector<CWallet*> vpwallets;
+static CCriticalSection cs_wallets;
+static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets);
bool AddWallet(CWallet* wallet)
{
+ LOCK(cs_wallets);
assert(wallet);
std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i != vpwallets.end()) return false;
@@ -47,6 +50,7 @@ bool AddWallet(CWallet* wallet)
bool RemoveWallet(CWallet* wallet)
{
+ LOCK(cs_wallets);
assert(wallet);
std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false;
@@ -56,16 +60,19 @@ bool RemoveWallet(CWallet* wallet)
bool HasWallets()
{
+ LOCK(cs_wallets);
return !vpwallets.empty();
}
std::vector<CWallet*> GetWallets()
{
+ LOCK(cs_wallets);
return vpwallets;
}
CWallet* GetWallet(const std::string& name)
{
+ LOCK(cs_wallets);
for (CWallet* wallet : vpwallets) {
if (wallet->GetName() == name) return wallet;
}
@@ -447,7 +454,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
}
-void CWallet::SetBestChain(const CBlockLocator& loc)
+void CWallet::ChainStateFlushed(const CBlockLocator& loc)
{
WalletBatch batch(*database);
batch.WriteBestBlock(loc);
@@ -1738,23 +1745,27 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
fAbortRescan = false;
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
CBlockIndex* tip = nullptr;
- double dProgressStart;
- double dProgressTip;
+ double progress_begin;
+ double progress_end;
{
LOCK(cs_main);
- tip = chainActive.Tip();
- dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex);
- dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip);
+ progress_begin = GuessVerificationProgress(chainParams.TxData(), pindex);
+ if (pindexStop == nullptr) {
+ tip = chainActive.Tip();
+ progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
+ } else {
+ progress_end = GuessVerificationProgress(chainParams.TxData(), pindexStop);
+ }
}
- double gvp = dProgressStart;
- while (pindex && !fAbortRescan)
+ double progress_current = progress_begin;
+ while (pindex && !fAbortRescan && !ShutdownRequested())
{
- if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) {
- ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
+ if (pindex->nHeight % 100 == 0 && progress_end - progress_begin > 0.0) {
+ ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100))));
}
if (GetTime() >= nNow + 60) {
nNow = GetTime();
- LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, gvp);
+ LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, progress_current);
}
CBlock block;
@@ -1778,16 +1789,18 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
{
LOCK(cs_main);
pindex = chainActive.Next(pindex);
- gvp = GuessVerificationProgress(chainParams.TxData(), pindex);
- if (tip != chainActive.Tip()) {
+ progress_current = GuessVerificationProgress(chainParams.TxData(), pindex);
+ if (pindexStop == nullptr && tip != chainActive.Tip()) {
tip = chainActive.Tip();
// in case the tip has changed, update progress max
- dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip);
+ progress_end = GuessVerificationProgress(chainParams.TxData(), tip);
}
}
}
if (pindex && fAbortRescan) {
- LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, gvp);
+ LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current);
+ } else if (pindex && ShutdownRequested()) {
+ LogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current);
}
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}
@@ -2665,7 +2678,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend)
{
// If -changetype is specified, always use that change type.
- if (change_type != OutputType::NONE) {
+ if (change_type != OutputType::CHANGE_AUTO) {
return change_type;
}
@@ -4032,7 +4045,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
return nullptr;
}
- walletInstance->SetBestChain(chainActive.GetLocator());
+ walletInstance->ChainStateFlushed(chainActive.GetLocator());
} else if (gArgs.IsArgSet("-usehd")) {
bool useHD = gArgs.GetBoolArg("-usehd", true);
if (walletInstance->IsHDEnabled() && !useHD) {
@@ -4045,16 +4058,12 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
}
- walletInstance->m_default_address_type = ParseOutputType(gArgs.GetArg("-addresstype", ""), DEFAULT_ADDRESS_TYPE);
- if (walletInstance->m_default_address_type == OutputType::NONE) {
+ if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) {
InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", "")));
return nullptr;
}
- // If changetype is set in config file or parameter, check that it's valid.
- // Default to OutputType::NONE if not set.
- walletInstance->m_default_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OutputType::NONE);
- if (walletInstance->m_default_change_type == OutputType::NONE && !gArgs.GetArg("-changetype", "").empty()) {
+ if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) {
InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", "")));
return nullptr;
}
@@ -4174,7 +4183,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true);
}
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
- walletInstance->SetBestChain(chainActive.GetLocator());
+ walletInstance->ChainStateFlushed(chainActive.GetLocator());
walletInstance->database->IncrementUpdateCounter();
// Restore wallet transaction metadata after -zapwallettxes=1
@@ -4302,19 +4311,19 @@ static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
-OutputType ParseOutputType(const std::string& type, OutputType default_type)
+bool ParseOutputType(const std::string& type, OutputType& output_type)
{
- if (type.empty()) {
- return default_type;
- } else if (type == OUTPUT_TYPE_STRING_LEGACY) {
- return OutputType::LEGACY;
+ if (type == OUTPUT_TYPE_STRING_LEGACY) {
+ output_type = OutputType::LEGACY;
+ return true;
} else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
- return OutputType::P2SH_SEGWIT;
+ output_type = OutputType::P2SH_SEGWIT;
+ return true;
} else if (type == OUTPUT_TYPE_STRING_BECH32) {
- return OutputType::BECH32;
- } else {
- return OutputType::NONE;
+ output_type = OutputType::BECH32;
+ return true;
}
+ return false;
}
const std::string& FormatOutputType(OutputType type)
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 780c82ac36..3208a20f0f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -93,15 +93,24 @@ enum WalletFeature
};
enum class OutputType {
- NONE,
LEGACY,
P2SH_SEGWIT,
BECH32,
+
+ /**
+ * Special output type for change outputs only. Automatically choose type
+ * based on address type setting and the types other of non-change outputs
+ * (see -changetype option documentation and implementation in
+ * CWallet::TransactionChangeType for details).
+ */
+ CHANGE_AUTO,
};
//! Default for -addresstype
constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::P2SH_SEGWIT};
+//! Default for -changetype
+constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO};
/** A key pool entry */
class CKeyPool
@@ -973,7 +982,7 @@ public:
CFeeRate m_fallback_fee{DEFAULT_FALLBACK_FEE};
CFeeRate m_discard_rate{DEFAULT_DISCARD_FEE};
OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE};
- OutputType m_default_change_type{OutputType::NONE}; // Default to OutputType::NONE if not set by -changetype
+ OutputType m_default_change_type{DEFAULT_CHANGE_TYPE};
bool NewKeyPool();
size_t KeypoolCountExternalKeys();
@@ -1013,7 +1022,7 @@ public:
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetChange(const CTransaction& tx) const;
- void SetBestChain(const CBlockLocator& loc) override;
+ void ChainStateFlushed(const CBlockLocator& loc) override;
DBErrors LoadWallet(bool& fFirstRunRet);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
@@ -1218,7 +1227,7 @@ public:
}
};
-OutputType ParseOutputType(const std::string& str, OutputType default_type);
+bool ParseOutputType(const std::string& str, OutputType& output_type);
const std::string& FormatOutputType(OutputType type);
/**
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 5b275131af..4d1a6d48d0 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -246,7 +246,7 @@ public:
}
};
-bool
+static bool
ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CWalletScanState &wss, std::string& strType, std::string& strErr)
{
diff --git a/src/warnings.cpp b/src/warnings.cpp
index 572c766600..dc4e6e4842 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -40,7 +40,6 @@ void SetfLargeWorkInvalidChainFound(bool flag)
std::string GetWarnings(const std::string& strFor)
{
std::string strStatusBar;
- std::string strRPC;
std::string strGUI;
const std::string uiAlertSeperator = "<hr />";
@@ -51,9 +50,6 @@ std::string GetWarnings(const std::string& strFor)
strGUI = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
}
- if (gArgs.GetBoolArg("-testsafemode", DEFAULT_TESTSAFEMODE))
- strStatusBar = strRPC = strGUI = "testsafemode enabled";
-
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
@@ -63,12 +59,12 @@ std::string GetWarnings(const std::string& strFor)
if (fLargeWorkForkFound)
{
- strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
+ strStatusBar = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
}
else if (fLargeWorkInvalidChainFound)
{
- strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
+ strStatusBar = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
}
@@ -76,8 +72,6 @@ std::string GetWarnings(const std::string& strFor)
return strGUI;
else if (strFor == "statusbar")
return strStatusBar;
- else if (strFor == "rpc")
- return strRPC;
assert(!"GetWarnings(): invalid parameter");
return "error";
}
diff --git a/src/warnings.h b/src/warnings.h
index 3d7ac5aab4..904e8c0440 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -15,13 +15,10 @@ bool GetfLargeWorkForkFound();
void SetfLargeWorkInvalidChainFound(bool flag);
/** Format a string that describes several potential problems detected by the core.
* strFor can have three values:
- * - "rpc": get critical warnings, which should put the client in safe mode if non-empty
* - "statusbar": get all warnings
* - "gui": get all warnings, translated (where possible) for GUI
* This function only returns the highest priority warning of the set selected by strFor.
*/
std::string GetWarnings(const std::string& strFor);
-static const bool DEFAULT_TESTSAFEMODE = false;
-
#endif // BITCOIN_WARNINGS_H
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 38b76239e5..17d3ddae4a 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -82,10 +82,7 @@ class FullBlockTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0] # convenience reference to the node
- # reconnect_p2p() expects the network thread to be running
- network_thread_start()
-
- self.reconnect_p2p()
+ self.bootstrap_p2p() # Add one p2p connection to the node
self.block_heights = {}
self.coinbase_key = CECKey()
@@ -1296,14 +1293,10 @@ class FullBlockTest(BitcoinTestFramework):
self.blocks[block_number] = block
return block
- def reconnect_p2p(self):
+ def bootstrap_p2p(self):
"""Add a P2P connection to the node.
- The node gets disconnected several times in this test. This helper
- method reconnects the p2p and restarts the network thread."""
-
- network_thread_join()
- self.nodes[0].disconnect_p2ps()
+ Helper to connect and wait for version handshake."""
self.nodes[0].add_p2p_connection(P2PDataStore())
network_thread_start()
# We need to wait for the initial getheaders from the peer before we
@@ -1314,6 +1307,15 @@ class FullBlockTest(BitcoinTestFramework):
# unexpectedly disconnected if the DoS score for that error is 50.
self.nodes[0].p2p.wait_for_getheaders(timeout=5)
+ def reconnect_p2p(self):
+ """Tear down and bootstrap the P2P connection to the node.
+
+ The node gets disconnected several times in this test. This helper
+ method reconnects the p2p and restarts the network thread."""
+ self.nodes[0].disconnect_p2ps()
+ network_thread_join()
+ self.bootstrap_p2p()
+
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index 3adde8dd73..11a52b9ee2 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -124,7 +124,7 @@ class PruneTest(BitcoinTestFramework):
# Reboot node 1 to clear its mempool (hopefully make the invalidate faster)
# Lower the block max size so we don't keep mining all our big mempool transactions (from disconnected blocks)
self.stop_node(1)
- self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5", "-disablesafemode"])
+ self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5"])
height = self.nodes[1].getblockcount()
self.log.info("Current block height: %d" % height)
@@ -147,7 +147,7 @@ class PruneTest(BitcoinTestFramework):
# Reboot node1 to clear those giant tx's from mempool
self.stop_node(1)
- self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5", "-disablesafemode"])
+ self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5"])
self.log.info("Generating new longer chain of 300 more blocks")
self.nodes[1].generate(300)
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index e835b9d777..a47c42829a 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -303,8 +303,10 @@ class SegWitTest(BitcoinTestFramework):
v = self.nodes[0].getaddressinfo(i)
if (v['isscript']):
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
- # bare and p2sh multisig with compressed keys should always be spendable
- spendable_anytime.extend([bare, p2sh])
+ # p2sh multisig with compressed keys should always be spendable
+ spendable_anytime.extend([p2sh])
+ # bare multisig can be watched and signed, but is not treated as ours
+ solvable_after_importaddress.extend([bare])
# P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress
spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh])
else:
@@ -320,8 +322,10 @@ class SegWitTest(BitcoinTestFramework):
v = self.nodes[0].getaddressinfo(i)
if (v['isscript']):
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
- # bare and p2sh multisig with uncompressed keys should always be spendable
- spendable_anytime.extend([bare, p2sh])
+ # p2sh multisig with uncompressed keys should always be spendable
+ spendable_anytime.extend([p2sh])
+ # bare multisig can be watched and signed, but is not treated as ours
+ solvable_after_importaddress.extend([bare])
# P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen
unseen_anytime.extend([p2wsh, p2sh_p2wsh])
else:
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 69ce529ad6..8a0961be1f 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -6,24 +6,48 @@
In this test we connect to one node over p2p, and test tx requests."""
from test_framework.blocktools import create_block, create_coinbase, create_transaction
-from test_framework.messages import COIN
-from test_framework.mininode import network_thread_start, P2PDataStore
+from test_framework.messages import (
+ COIN,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxOut,
+)
+from test_framework.mininode import network_thread_start, P2PDataStore, network_thread_join
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ wait_until,
+)
-class InvalidTxRequestTest(BitcoinTestFramework):
+class InvalidTxRequestTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [["-whitelist=127.0.0.1"]]
+
+ def bootstrap_p2p(self, *, num_connections=1):
+ """Add a P2P connection to the node.
+
+ Helper to connect and wait for version handshake."""
+ for _ in range(num_connections):
+ self.nodes[0].add_p2p_connection(P2PDataStore())
+ network_thread_start()
+ self.nodes[0].p2p.wait_for_verack()
+
+ def reconnect_p2p(self, **kwargs):
+ """Tear down and bootstrap the P2P connection to the node.
+
+ The node gets disconnected several times in this test. This helper
+ method reconnects the p2p and restarts the network thread."""
+ self.nodes[0].disconnect_p2ps()
+ network_thread_join()
+ self.bootstrap_p2p(**kwargs)
def run_test(self):
- # Add p2p connection to node0
node = self.nodes[0] # convenience reference to the node
- node.add_p2p_connection(P2PDataStore())
- network_thread_start()
- node.p2p.wait_for_verack()
+ self.bootstrap_p2p() # Add one p2p connection to the node
best_block = self.nodes[0].getbestblockhash()
tip = int(best_block, 16)
@@ -44,12 +68,73 @@ class InvalidTxRequestTest(BitcoinTestFramework):
# b'\x64' is OP_NOTIF
# Transaction will be rejected with code 16 (REJECT_INVALID)
+ # and we get disconnected immediately
+ self.log.info('Test a transaction that is rejected')
tx1 = create_transaction(block1.vtx[0], 0, b'\x64', 50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=False, reject_code=16, reject_reason=b'mandatory-script-verify-flag-failed (Invalid OP_IF construction)')
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+
+ # Make two p2p connections to provide the node with orphans
+ # * p2ps[0] will send valid orphan txs (one with low fee)
+ # * p2ps[1] will send an invalid orphan tx (and is later disconnected for that)
+ self.reconnect_p2p(num_connections=2)
+
+ self.log.info('Test orphan transaction handling ... ')
+ # Create a root transaction that we withold until all dependend transactions
+ # are sent out and in the orphan cache
+ tx_withhold = CTransaction()
+ tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
+ tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=b'\x51'))
+ tx_withhold.calc_sha256()
+
+ # Our first orphan tx with some outputs to create further orphan txs
+ tx_orphan_1 = CTransaction()
+ tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
+ tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51')] * 3
+ tx_orphan_1.calc_sha256()
+
+ # A valid transaction with low fee
+ tx_orphan_2_no_fee = CTransaction()
+ tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
+ tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51'))
+
+ # A valid transaction with sufficient fee
+ tx_orphan_2_valid = CTransaction()
+ tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
+ tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=b'\x51'))
+ tx_orphan_2_valid.calc_sha256()
+
+ # An invalid transaction with negative fee
+ tx_orphan_2_invalid = CTransaction()
+ tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
+ tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=b'\x51'))
+
+ self.log.info('Send the orphans ... ')
+ # Send valid orphan txs from p2ps[0]
+ node.p2p.send_txs_and_test([tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid], node, success=False)
+ # Send invalid tx from p2ps[1]
+ node.p2ps[1].send_txs_and_test([tx_orphan_2_invalid], node, success=False)
+
+ assert_equal(0, node.getmempoolinfo()['size']) # Mempool should be empty
+ assert_equal(2, len(node.getpeerinfo())) # p2ps[1] is still connected
+
+ self.log.info('Send the withhold tx ... ')
+ node.p2p.send_txs_and_test([tx_withhold], node, success=True)
+
+ # Transactions that should end up in the mempool
+ expected_mempool = {
+ t.hash
+ for t in [
+ tx_withhold, # The transaction that is the root for all orphans
+ tx_orphan_1, # The orphan transaction that splits the coins
+ tx_orphan_2_valid, # The valid transaction (with sufficient fee)
+ ]
+ }
+ # Transactions that do not end up in the mempool
+ # tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
+ # tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)
- # Verify valid transaction
- tx1 = create_transaction(block1.vtx[0], 0, b'', 50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=True)
+ wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
+ assert_equal(expected_mempool, set(node.getrawmempool()))
if __name__ == '__main__':
diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py
index 7b7c596506..2e0500e7c4 100755
--- a/test/functional/rpc_deprecated.py
+++ b/test/functional/rpc_deprecated.py
@@ -49,6 +49,7 @@ class DeprecatedRpcTest(BitcoinTestFramework):
#
address0 = self.nodes[0].getnewaddress()
self.nodes[0].generatetoaddress(101, address0)
+ self.sync_all()
address1 = self.nodes[1].getnewaddress()
self.nodes[1].generatetoaddress(101, address1)
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 5fb9a361d9..0f09c3c552 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -224,7 +224,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
- assert_raises_rpc_error(-5, "Unknown change type", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
+ assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'})
dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type'])
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index aba2841682..7c2125a177 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -554,13 +554,13 @@ class P2PDataStore(P2PInterface):
if reject_reason is not None:
wait_until(lambda: self.reject_reason_received == reject_reason, lock=mininode_lock)
- def send_txs_and_test(self, txs, rpc, success=True, reject_code=None, reject_reason=None):
+ def send_txs_and_test(self, txs, rpc, success=True, expect_disconnect=False, reject_code=None, reject_reason=None):
"""Send txs to test node and test whether they're accepted to the mempool.
- add all txs to our tx_store
- send tx messages for all txs
- - if success is True: assert that the tx is accepted to the mempool
- - if success is False: assert that the tx is not accepted to the mempool
+ - if success is True/False: assert that the txs are/are not accepted to the mempool
+ - if expect_disconnect is True: Skip the sync with ping
- if reject_code and reject_reason are set: assert that the correct reject message is received."""
with mininode_lock:
@@ -573,7 +573,10 @@ class P2PDataStore(P2PInterface):
for tx in txs:
self.send_message(msg_tx(tx))
- self.sync_with_ping()
+ if expect_disconnect:
+ self.wait_for_disconnect()
+ else:
+ self.sync_with_ping()
raw_mempool = rpc.getrawmempool()
if success:
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index f5e1f3d4f7..ff4b480165 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -201,6 +201,7 @@ def main():
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('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs")
+ parser.add_argument('--failfast', action='store_true', help='stop execution after the first test failure')
args, unknown_args = parser.parse_known_args()
# args to be passed on always start with two dashes; tests are the remaining unknown args
@@ -283,9 +284,21 @@ def main():
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"], tmpdir, args.jobs, args.coverage, passon_args, args.combinedlogslen)
+ run_tests(
+ test_list,
+ config["environment"]["SRCDIR"],
+ config["environment"]["BUILDDIR"],
+ tmpdir,
+ jobs=args.jobs,
+ enable_coverage=args.coverage,
+ args=passon_args,
+ combined_logs_len=args.combinedlogslen,
+ failfast=args.failfast,
+ )
+
+def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False):
+ args = args or []
-def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=[], combined_logs_len=0):
# Warn if bitcoind is already running (unix only)
try:
if subprocess.check_output(["pidof", "bitcoind"]) is not None:
@@ -346,6 +359,10 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
combined_logs, _ = subprocess.Popen([sys.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
print("\n".join(deque(combined_logs.splitlines(), combined_logs_len)))
+ if failfast:
+ logging.debug("Early exiting after test failure")
+ break
+
print_results(test_results, max_len_name, (int(time.time() - start_time)))
if coverage:
@@ -360,6 +377,10 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
all_passed = all(map(lambda test_result: test_result.was_successful, test_results))
+ # This will be a no-op unless failfast is True in which case there may be dangling
+ # processes which need to be killed.
+ job_queue.kill_and_join()
+
sys.exit(not all_passed)
def print_results(test_results, max_len_name, runtime):
@@ -450,6 +471,17 @@ class TestHandler:
return TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr
print('.', end='', flush=True)
+ def kill_and_join(self):
+ """Send SIGKILL to all jobs and block until all have ended."""
+ procs = [i[2] for i in self.jobs]
+
+ for proc in procs:
+ proc.kill()
+
+ for proc in procs:
+ proc.wait()
+
+
class TestResult():
def __init__(self, name, status, time):
self.name = name
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index 5d2428e6ef..7658d78383 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -280,7 +280,10 @@ class AddressTypeTest(BitcoinTestFramework):
self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent')
self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
- self.log.info('getrawchangeaddress fails with invalid changetype argument')
+ self.log.info('test invalid address type arguments')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], None, '')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '')
assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')
self.log.info("Nodes with changetype=p2sh-segwit never use a P2WPKH change output")
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index bfe90957a7..0e095a6132 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -3,8 +3,20 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the wallet."""
+from decimal import Decimal
+import time
+
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ assert_fee_amount,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ sync_blocks,
+ sync_mempools,
+ wait_until,
+)
class WalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -17,9 +29,9 @@ class WalletTest(BitcoinTestFramework):
self.start_node(0)
self.start_node(1)
self.start_node(2)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
self.sync_all([self.nodes[0:3]])
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
@@ -112,11 +124,11 @@ class WalletTest(BitcoinTestFramework):
self.nodes[2].lockunspent(True, [unspent_0])
assert_equal(len(self.nodes[2].listlockunspent()), 0)
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
- self.nodes[2].lockunspent, False,
- [{"txid": "0000000000000000000000000000000000", "vout": 0}])
+ self.nodes[2].lockunspent, False,
+ [{"txid": "0000000000000000000000000000000000", "vout": 0}])
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
- self.nodes[2].lockunspent, False,
- [{"txid": unspent_0["txid"], "vout": 999}])
+ self.nodes[2].lockunspent, False,
+ [{"txid": unspent_0["txid"], "vout": 999}])
# Have node1 generate 100 blocks (so node0 can recover the fee)
self.nodes[1].generate(100)
@@ -124,7 +136,7 @@ class WalletTest(BitcoinTestFramework):
# node0 should end up with 100 btc in block rewards plus fees, but
# minus the 21 plus fees sent to node2
- assert_equal(self.nodes[0].getbalance(), 100-21)
+ assert_equal(self.nodes[0].getbalance(), 100 - 21)
assert_equal(self.nodes[2].getbalance(), 21)
# Node0 should have two unspent outputs.
@@ -138,7 +150,7 @@ class WalletTest(BitcoinTestFramework):
for utxo in node0utxos:
inputs = []
outputs = {}
- inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
+ inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] - 3
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))
@@ -153,7 +165,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[2].getbalance(), 94)
- assert_equal(self.nodes[2].getbalance("from1"), 94-21)
+ assert_equal(self.nodes[2].getbalance("from1"), 94 - 21)
# Verify that a spent output cannot be locked anymore
spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
@@ -215,91 +227,90 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1)
assert_equal(self.nodes[0].getunconfirmedbalance(), 1)
- #check if we can list zero value tx as available coins
- #1. create rawtx
- #2. hex-changed one output to 0.0
- #3. sign and send
- #4. check if recipient (node0) can list the zero value tx
+ # check if we can list zero value tx as available coins
+ # 1. create raw_tx
+ # 2. hex-changed one output to 0.0
+ # 3. sign and send
+ # 4. check if recipient (node0) can list the zero value tx
usp = self.nodes[1].listunspent()
- inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}]
+ inputs = [{"txid": usp[0]['txid'], "vout": usp[0]['vout']}]
outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}
- rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") #replace 11.11 with 0.0 (int32)
- decRawTx = self.nodes[1].decoderawtransaction(rawTx)
- signedRawTx = self.nodes[1].signrawtransactionwithwallet(rawTx)
- decRawTx = self.nodes[1].decoderawtransaction(signedRawTx['hex'])
- zeroValueTxid= decRawTx['txid']
- self.nodes[1].sendrawtransaction(signedRawTx['hex'])
+ raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") # replace 11.11 with 0.0 (int32)
+ signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx)
+ decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
+ zero_value_txid = decoded_raw_tx['txid']
+ self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])
self.sync_all()
- self.nodes[1].generate(1) #mine a block
+ self.nodes[1].generate(1) # mine a block
self.sync_all()
- unspentTxs = self.nodes[0].listunspent() #zero value tx must be in listunspents output
+ unspent_txs = self.nodes[0].listunspent() # zero value tx must be in listunspents output
found = False
- for uTx in unspentTxs:
- if uTx['txid'] == zeroValueTxid:
+ for uTx in unspent_txs:
+ if uTx['txid'] == zero_value_txid:
found = True
assert_equal(uTx['amount'], Decimal('0'))
assert(found)
- #do some -walletbroadcast tests
+ # do some -walletbroadcast tests
self.stop_nodes()
self.start_node(0, ["-walletbroadcast=0"])
self.start_node(1, ["-walletbroadcast=0"])
self.start_node(2, ["-walletbroadcast=0"])
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
self.sync_all([self.nodes[0:3]])
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
- txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
- self.nodes[1].generate(1) #mine a block, tx should not be in there
+ txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
+ tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
+ self.nodes[1].generate(1) # mine a block, tx should not be in there
self.sync_all([self.nodes[0:3]])
- assert_equal(self.nodes[2].getbalance(), node_2_bal) #should not be changed because tx was not broadcasted
+ assert_equal(self.nodes[2].getbalance(), node_2_bal) # should not be changed because tx was not broadcasted
- #now broadcast from another node, mine a block, sync, and check the balance
- self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
+ # now broadcast from another node, mine a block, sync, and check the balance
+ self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
self.nodes[1].generate(1)
self.sync_all([self.nodes[0:3]])
node_2_bal += 2
- txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
+ tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- #create another tx
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
+ # create another tx
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
- #restart the nodes with -walletbroadcast=1
+ # restart the nodes with -walletbroadcast=1
self.stop_nodes()
self.start_node(0)
self.start_node(1)
self.start_node(2)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
sync_blocks(self.nodes[0:3])
self.nodes[0].generate(1)
sync_blocks(self.nodes[0:3])
node_2_bal += 2
- #tx should be added to balance because after restarting the nodes tx should be broadcast
+ # tx should be added to balance because after restarting the nodes tx should be broadcast
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- #send a tx with value in a string (PR#6380 +)
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-2'))
+ # send a tx with value in a string (PR#6380 +)
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-2'))
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.0001'))
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-0.0001'))
- #check if JSON parser can handle scientific notation in strings
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.0001'))
+ # check if JSON parser can handle scientific notation in strings
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-0.0001'))
# This will raise an exception because the amount type is wrong
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
@@ -322,8 +333,8 @@ class WalletTest(BitcoinTestFramework):
# 4. Check that the unspents after import are not spendable
assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": False})
+ {"address": address_to_import},
+ {"spendable": False})
# 5. Import private key of the previously imported address on node1
priv_key = self.nodes[2].dumpprivkey(address_to_import)
@@ -331,17 +342,17 @@ class WalletTest(BitcoinTestFramework):
# 6. Check that the unspents are now spendable on node1
assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": True})
+ {"address": address_to_import},
+ {"spendable": True})
# Mine a block from node0 to an address from node1
- cbAddr = self.nodes[1].getnewaddress()
- blkHash = self.nodes[0].generatetoaddress(1, cbAddr)[0]
- cbTxId = self.nodes[0].getblock(blkHash)['tx'][0]
+ coinbase_addr = self.nodes[1].getnewaddress()
+ block_hash = self.nodes[0].generatetoaddress(1, coinbase_addr)[0]
+ coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
self.sync_all([self.nodes[0:3]])
# Check that the txid and balance is found by node1
- self.nodes[1].gettransaction(cbTxId)
+ self.nodes[1].gettransaction(coinbase_txid)
# check if wallet or blockchain maintenance changes the balance
self.sync_all([self.nodes[0:3]])
@@ -361,7 +372,7 @@ class WalletTest(BitcoinTestFramework):
label = self.nodes[0].getaccount(addr)
assert_equal(label, s)
assert(s in self.nodes[0].listaccounts().keys())
- self.nodes[0].ensure_ascii = True # restore to default
+ self.nodes[0].ensure_ascii = True # restore to default
# maintenance tests
maintenance = [
@@ -377,9 +388,9 @@ class WalletTest(BitcoinTestFramework):
self.log.info("check " + m)
self.stop_nodes()
# set lower ancestor limit for later
- self.start_node(0, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)])
- self.start_node(1, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)])
- self.start_node(2, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)])
+ self.start_node(0, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(1, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(2, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
if m == '-reindex':
# reindex will leave rpc warm up "early"; Wait for it to finish
wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
@@ -400,7 +411,7 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].generate(1)
node0_balance = self.nodes[0].getbalance()
# Split into two chains
- rawtx = self.nodes[0].createrawtransaction([{"txid":singletxid, "vout":0}], {chain_addrs[0]:node0_balance/2-Decimal('0.01'), chain_addrs[1]:node0_balance/2-Decimal('0.01')})
+ rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx)
singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
self.nodes[0].generate(1)
@@ -411,10 +422,10 @@ class WalletTest(BitcoinTestFramework):
# So we should be able to generate exactly chainlimit txs for each original output
sending_addr = self.nodes[1].getnewaddress()
txid_list = []
- for i in range(chainlimit*2):
+ for i in range(chainlimit * 2):
txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
- assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit*2)
- assert_equal(len(txid_list), chainlimit*2)
+ assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
+ assert_equal(len(txid_list), chainlimit * 2)
# Without walletrejectlongchains, we will still generate a txid
# The tx will be stored in the wallet but not accepted to the mempool
@@ -422,26 +433,26 @@ class WalletTest(BitcoinTestFramework):
assert(extra_txid not in self.nodes[0].getrawmempool())
assert(extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()])
self.nodes[0].abandontransaction(extra_txid)
- total_txs = len(self.nodes[0].listtransactions("*",99999))
+ total_txs = len(self.nodes[0].listtransactions("*", 99999))
# Try with walletrejectlongchains
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
self.stop_node(0)
- self.start_node(0, extra_args=["-deprecatedrpc=accounts", "-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)])
+ self.start_node(0, extra_args=["-deprecatedrpc=accounts", "-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
# wait for loadmempool
timeout = 10
- while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit*2):
+ while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 2):
time.sleep(0.5)
timeout -= 0.5
- assert_equal(len(self.nodes[0].getrawmempool()), chainlimit*2)
+ assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)
node0_balance = self.nodes[0].getbalance()
# With walletrejectlongchains we will not create the tx and store it in our wallet.
assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
# Verify nothing new in wallet
- assert_equal(total_txs, len(self.nodes[0].listtransactions("*",99999)))
+ assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
# Test getaddressinfo. Note that these addresses are taken from disablewallet.py
assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 6775d8b46d..baf933f079 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -46,10 +46,10 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
if self.call == Call.single:
if self.data == Data.address:
response = self.try_rpc(self.node.importaddress, self.address["address"], self.label,
- self.rescan == Rescan.yes)
+ self.rescan == Rescan.yes)
elif self.data == Data.pub:
response = self.try_rpc(self.node.importpubkey, self.address["pubkey"], self.label,
- self.rescan == Rescan.yes)
+ self.rescan == Rescan.yes)
elif self.data == Data.priv:
response = self.try_rpc(self.node.importprivkey, self.key, self.label, self.rescan == Rescan.yes)
assert_equal(response, None)
diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py
index d0ec290f36..9cee9aa49a 100755
--- a/test/functional/wallet_importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
@@ -3,8 +3,13 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the importprunedfunds and removeprunedfunds RPCs."""
+from decimal import Decimal
+
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
class ImportPrunedFundsTest(BitcoinTestFramework):
def set_test_params(self):
@@ -24,18 +29,18 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
address2 = self.nodes[0].getnewaddress()
# privkey
address3 = self.nodes[0].getnewaddress()
- address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
+ address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
- #Check only one address
+ # Check only one address
address_info = self.nodes[0].getaddressinfo(address1)
assert_equal(address_info['ismine'], True)
self.sync_all()
- #Node 1 sync test
- assert_equal(self.nodes[1].getblockcount(),101)
+ # Node 1 sync test
+ assert_equal(self.nodes[1].getblockcount(), 101)
- #Address Test - before import
+ # Address Test - before import
address_info = self.nodes[1].getaddressinfo(address1)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
@@ -48,7 +53,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
- #Send funds to self
+ # Send funds to self
txnid1 = self.nodes[0].sendtoaddress(address1, 0.1)
self.nodes[0].generate(1)
rawtxn1 = self.nodes[0].gettransaction(txnid1)['hex']
@@ -66,19 +71,19 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
self.sync_all()
- #Import with no affiliated address
+ # Import with no affiliated address
assert_raises_rpc_error(-5, "No addresses", self.nodes[1].importprunedfunds, rawtxn1, proof1)
balance1 = self.nodes[1].getbalance("", 0, True)
assert_equal(balance1, Decimal(0))
- #Import with affiliated address with no rescan
+ # Import with affiliated address with no rescan
self.nodes[1].importaddress(address2, "add2", False)
self.nodes[1].importprunedfunds(rawtxn2, proof2)
balance2 = self.nodes[1].getbalance("add2", 0, True)
assert_equal(balance2, Decimal('0.05'))
- #Import with private key with no rescan
+ # Import with private key with no rescan
self.nodes[1].importprivkey(privkey=address3_privkey, label="add3", rescan=False)
self.nodes[1].importprunedfunds(rawtxn3, proof3)
balance3 = self.nodes[1].getbalance("add3", 0, False)
@@ -86,7 +91,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
balance3 = self.nodes[1].getbalance("*", 0, True)
assert_equal(balance3, Decimal('0.075'))
- #Addresses Test - after import
+ # Addresses Test - after import
address_info = self.nodes[1].getaddressinfo(address1)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
@@ -97,7 +102,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], True)
- #Remove transactions
+ # Remove transactions
assert_raises_rpc_error(-8, "Transaction does not exist in wallet.", self.nodes[1].removeprunedfunds, txnid1)
balance1 = self.nodes[1].getbalance("*", 0, True)
diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py
index aba5d642bc..e0e20cc9a3 100755
--- a/test/functional/wallet_listreceivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -51,37 +51,37 @@ class ReceivedByTest(BitcoinTestFramework):
{"address": empty_addr},
{"address": empty_addr, "label": "", "amount": 0, "confirmations": 0, "txids": []})
- #Test Address filtering
- #Only on addr
- expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}
+ # Test Address filtering
+ # Only on addr
+ expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
- assert_array_result(res, {"address":addr}, expected)
+ assert_array_result(res, {"address": addr}, expected)
assert_equal(len(res), 1)
- #Error on invalid address
+ # Error on invalid address
assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling")
- #Another address receive money
+ # Another address receive money
res = self.nodes[1].listreceivedbyaddress(0, True, True)
- assert_equal(len(res), 2) #Right now 2 entries
+ assert_equal(len(res), 2) # Right now 2 entries
other_addr = self.nodes[1].getnewaddress()
txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
self.nodes[0].generate(1)
self.sync_all()
- #Same test as above should still pass
- expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":11, "txids":[txid,]}
+ # Same test as above should still pass
+ expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 11, "txids": [txid, ]}
res = self.nodes[1].listreceivedbyaddress(0, True, True, addr)
- assert_array_result(res, {"address":addr}, expected)
+ assert_array_result(res, {"address": addr}, expected)
assert_equal(len(res), 1)
- #Same test as above but with other_addr should still pass
- expected = {"address":other_addr, "label":"", "amount":Decimal("0.1"), "confirmations":1, "txids":[txid2,]}
+ # Same test as above but with other_addr should still pass
+ expected = {"address": other_addr, "label": "", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]}
res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
- assert_array_result(res, {"address":other_addr}, expected)
+ assert_array_result(res, {"address": other_addr}, expected)
assert_equal(len(res), 1)
- #Should be two entries though without filter
+ # Should be two entries though without filter
res = self.nodes[1].listreceivedbyaddress(0, True, True)
- assert_equal(len(res), 3) #Became 3 entries
+ assert_equal(len(res), 3) # Became 3 entries
- #Not on random addr
- other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
+ # Not on random addr
+ other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
assert_equal(len(res), 0)
@@ -112,8 +112,8 @@ class ReceivedByTest(BitcoinTestFramework):
self.log.info("listreceivedbylabel + getreceivedbylabel Test")
# set pre-state
- addrArr = self.nodes[1].getnewaddress()
- label = self.nodes[1].getaccount(addrArr)
+ address = self.nodes[1].getnewaddress()
+ label = self.nodes[1].getaccount(address)
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
balance_by_label = self.nodes[1].getreceivedbylabel(label)
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 930bfcd7b0..50a3313e2f 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -150,26 +150,26 @@ class ListSinceBlockTest (BitcoinTestFramework):
# send from nodes[1] using utxo to nodes[0]
change = '%.8f' % (float(utxo['amount']) - 1.0003)
- recipientDict = {
+ recipient_dict = {
self.nodes[0].getnewaddress(): 1,
self.nodes[1].getnewaddress(): change,
}
- utxoDicts = [{
+ utxo_dicts = [{
'txid': utxo['txid'],
'vout': utxo['vout'],
}]
txid1 = self.nodes[1].sendrawtransaction(
self.nodes[1].signrawtransactionwithwallet(
- self.nodes[1].createrawtransaction(utxoDicts, recipientDict))['hex'])
+ self.nodes[1].createrawtransaction(utxo_dicts, recipient_dict))['hex'])
# send from nodes[2] using utxo to nodes[3]
- recipientDict2 = {
+ recipient_dict2 = {
self.nodes[3].getnewaddress(): 1,
self.nodes[2].getnewaddress(): change,
}
self.nodes[2].sendrawtransaction(
self.nodes[2].signrawtransactionwithwallet(
- self.nodes[2].createrawtransaction(utxoDicts, recipientDict2))['hex'])
+ self.nodes[2].createrawtransaction(utxo_dicts, recipient_dict2))['hex'])
# generate on both sides
lastblockhash = self.nodes[1].generate(3)[2]
@@ -225,16 +225,16 @@ class ListSinceBlockTest (BitcoinTestFramework):
utxos = self.nodes[2].listunspent()
utxo = utxos[0]
change = '%.8f' % (float(utxo['amount']) - 1.0003)
- recipientDict = {
+ recipient_dict = {
self.nodes[0].getnewaddress(): 1,
self.nodes[2].getnewaddress(): change,
}
- utxoDicts = [{
+ utxo_dicts = [{
'txid': utxo['txid'],
'vout': utxo['vout'],
}]
signedtxres = self.nodes[2].signrawtransactionwithwallet(
- self.nodes[2].createrawtransaction(utxoDicts, recipientDict))
+ self.nodes[2].createrawtransaction(utxo_dicts, recipient_dict))
assert signedtxres['complete']
signedtx = signedtxres['hex']
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index 5466bbf18b..883942cc19 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -3,13 +3,20 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the listtransactions API."""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.mininode import CTransaction, COIN
+from decimal import Decimal
from io import BytesIO
-def txFromHex(hexstring):
+from test_framework.mininode import CTransaction, COIN
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ bytes_to_hex_str,
+ hex_str_to_bytes,
+ sync_mempools,
+)
+
+def tx_from_hex(hexstring):
tx = CTransaction()
f = BytesIO(hex_str_to_bytes(hexstring))
tx.deserialize(f)
@@ -26,61 +33,61 @@ class ListTransactionsTest(BitcoinTestFramework):
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid},
- {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
+ {"txid": txid},
+ {"category": "send", "account": "", "amount": Decimal("-0.1"), "confirmations": 0})
assert_array_result(self.nodes[1].listtransactions(),
- {"txid":txid},
- {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
+ {"txid": txid},
+ {"category": "receive", "account": "", "amount": Decimal("0.1"), "confirmations": 0})
# mine a block, confirmations should change:
self.nodes[0].generate(1)
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid},
- {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
+ {"txid": txid},
+ {"category": "send", "account": "", "amount": Decimal("-0.1"), "confirmations": 1})
assert_array_result(self.nodes[1].listtransactions(),
- {"txid":txid},
- {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
+ {"txid": txid},
+ {"category": "receive", "account": "", "amount": Decimal("0.1"), "confirmations": 1})
# send-to-self:
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid, "category":"send"},
- {"amount":Decimal("-0.2")})
+ {"txid": txid, "category": "send"},
+ {"amount": Decimal("-0.2")})
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid, "category":"receive"},
- {"amount":Decimal("0.2")})
+ {"txid": txid, "category": "receive"},
+ {"amount": Decimal("0.2")})
# sendmany from node1: twice to self, twice to node2:
- send_to = { self.nodes[0].getnewaddress() : 0.11,
- self.nodes[1].getnewaddress() : 0.22,
- self.nodes[0].getaccountaddress("from1") : 0.33,
- self.nodes[1].getaccountaddress("toself") : 0.44 }
+ send_to = {self.nodes[0].getnewaddress(): 0.11,
+ self.nodes[1].getnewaddress(): 0.22,
+ self.nodes[0].getaccountaddress("from1"): 0.33,
+ self.nodes[1].getaccountaddress("toself"): 0.44}
txid = self.nodes[1].sendmany("", send_to)
self.sync_all()
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.11")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.11")},
+ {"txid": txid})
assert_array_result(self.nodes[0].listtransactions(),
- {"category":"receive","amount":Decimal("0.11")},
- {"txid":txid} )
+ {"category": "receive", "amount": Decimal("0.11")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.22")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.22")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"receive","amount":Decimal("0.22")},
- {"txid":txid} )
+ {"category": "receive", "amount": Decimal("0.22")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.33")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.33")},
+ {"txid": txid})
assert_array_result(self.nodes[0].listtransactions(),
- {"category":"receive","amount":Decimal("0.33")},
- {"txid":txid, "account" : "from1"} )
+ {"category": "receive", "amount": Decimal("0.33")},
+ {"txid": txid, "account": "from1"})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.44")},
- {"txid":txid, "account" : ""} )
+ {"category": "send", "amount": Decimal("-0.44")},
+ {"txid": txid, "account": ""})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"receive","amount":Decimal("0.44")},
- {"txid":txid, "account" : "toself"} )
+ {"category": "receive", "amount": Decimal("0.44")},
+ {"txid": txid, "account": "toself"})
pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
multisig = self.nodes[1].createmultisig(1, [pubkey])
@@ -90,8 +97,8 @@ class ListTransactionsTest(BitcoinTestFramework):
self.sync_all()
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
- {"category":"receive","amount":Decimal("0.1")},
- {"txid":txid, "account" : "watchonly"} )
+ {"category": "receive", "amount": Decimal("0.1")},
+ {"txid": txid, "account": "watchonly"})
self.run_rbf_opt_in_test()
@@ -117,9 +124,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# 1. Chain a few transactions that don't opt-in.
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
assert(not is_opt_in(self.nodes[0], txid_1))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})
# Tx2 will build off txid_1, still not opting in to RBF.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1)
@@ -129,7 +136,7 @@ class ListTransactionsTest(BitcoinTestFramework):
assert_equal(utxo_to_use["safe"], False)
# Create tx2 using createrawtransaction
- inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.999}
tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
@@ -137,51 +144,51 @@ class ListTransactionsTest(BitcoinTestFramework):
# ...and check the result
assert(not is_opt_in(self.nodes[1], txid_2))
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})
# Tx3 will opt-in to RBF
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
- inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": txid_2, "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[1].getnewaddress(): 0.998}
tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
- tx3_modified = txFromHex(tx3)
+ tx3_modified = tx_from_hex(tx3)
tx3_modified.vin[0].nSequence = 0
tx3 = bytes_to_hex_str(tx3_modified.serialize())
tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex']
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
assert(is_opt_in(self.nodes[0], txid_3))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
# that does.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
- inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.997}
tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
assert(not is_opt_in(self.nodes[1], txid_4))
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})
# Replace tx3, and check that tx4 becomes unknown
tx3_b = tx3_modified
- tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee
+ tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee
tx3_b = bytes_to_hex_str(tx3_b.serialize())
tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex']
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
assert(is_opt_in(self.nodes[0], txid_3b))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})
# Check gettransaction as well:
for n in self.nodes[0:2]:
@@ -197,7 +204,5 @@ class ListTransactionsTest(BitcoinTestFramework):
assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
-
if __name__ == '__main__':
ListTransactionsTest().main()
-
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index aee84f7e90..b4e4cb1686 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -5,7 +5,12 @@
"""Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs."""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ connect_nodes,
+ disconnect_nodes,
+ sync_blocks,
+)
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
@@ -26,9 +31,9 @@ class TxnMallTest(BitcoinTestFramework):
def run_test(self):
if self.options.segwit:
- output_type="p2sh-segwit"
+ output_type = "p2sh-segwit"
else:
- output_type="legacy"
+ output_type = "legacy"
# All nodes should start with 1,250 BTC:
starting_balance = 1250
@@ -53,28 +58,27 @@ class TxnMallTest(BitcoinTestFramework):
# Coins are sent to node1_address
node1_address = self.nodes[1].getnewaddress("from0")
- # Send tx1, and another transaction tx2 that won't be cloned
+ # Send tx1, and another transaction tx2 that won't be cloned
txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0)
txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0)
- # Construct a clone of tx1, to be malleated
- rawtx1 = self.nodes[0].getrawtransaction(txid1,1)
- clone_inputs = [{"txid":rawtx1["vin"][0]["txid"],"vout":rawtx1["vin"][0]["vout"]}]
- clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][0]["value"],
- rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][1]["value"]}
+ # Construct a clone of tx1, to be malleated
+ rawtx1 = self.nodes[0].getrawtransaction(txid1, 1)
+ clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"]}]
+ clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][0]["value"],
+ rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][1]["value"]}
clone_locktime = rawtx1["locktime"]
clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
# createrawtransaction randomizes the order of its outputs, so swap them if necessary.
# output 0 is at version+#inputs+input+sigstub+sequence+#outputs
# 40 BTC serialized is 00286bee00000000
- pos0 = 2*(4+1+36+1+4+1)
+ pos0 = 2 * (4 + 1 + 36 + 1 + 4 + 1)
hex40 = "00286bee00000000"
- output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16 : pos0 + 16 + 2], 0)
- if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0 : pos0 + 16] != hex40 or
- rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0 : pos0 + 16] == hex40):
- output0 = clone_raw[pos0 : pos0 + output_len]
- output1 = clone_raw[pos0 + output_len : pos0 + 2 * output_len]
+ output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16:pos0 + 16 + 2], 0)
+ if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0:pos0 + 16] != hex40 or rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0:pos0 + 16] == hex40):
+ output0 = clone_raw[pos0:pos0 + output_len]
+ output1 = clone_raw[pos0 + output_len:pos0 + 2 * output_len]
clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:]
# Use a different signature hash type to sign. This creates an equivalent but malleated clone.
@@ -142,7 +146,7 @@ class TxnMallTest(BitcoinTestFramework):
# Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured,
# less possible orphaned matured subsidy
expected += 100
- if (self.options.mine_block):
+ if (self.options.mine_block):
expected -= 50
assert_equal(self.nodes[0].getbalance(), expected)
assert_equal(self.nodes[0].getbalance("*", 0), expected)
@@ -153,16 +157,11 @@ class TxnMallTest(BitcoinTestFramework):
# "bar" should have been debited by (possibly unconfirmed) tx2
assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
# "" should have starting balance, less funding txes, plus subsidies
- assert_equal(self.nodes[0].getbalance("", 0), starting_balance
- - 1219
- + fund_foo_tx["fee"]
- - 29
- + fund_bar_tx["fee"]
- + 100)
+ assert_equal(self.nodes[0].getbalance("", 0),
+ starting_balance - 1219 + fund_foo_tx["fee"] - 29 + fund_bar_tx["fee"] + 100)
# Node1's "from0" account balance
assert_equal(self.nodes[1].getbalance("from0", 0), -(tx1["amount"] + tx2["amount"]))
if __name__ == '__main__':
TxnMallTest().main()
-
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index d644a94c73..d8d91132d1 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -3,9 +3,16 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the wallet accounts properly when there is a double-spend conflict."""
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ connect_nodes,
+ disconnect_nodes,
+ find_output,
+ sync_blocks,
+)
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
@@ -84,14 +91,14 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), expected)
# foo and bar accounts should be debited:
- assert_equal(self.nodes[0].getbalance("foo", 0), 1219+tx1["amount"]+tx1["fee"])
- assert_equal(self.nodes[0].getbalance("bar", 0), 29+tx2["amount"]+tx2["fee"])
+ assert_equal(self.nodes[0].getbalance("foo", 0), 1219 + tx1["amount"] + tx1["fee"])
+ assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
if self.options.mine_block:
assert_equal(tx1["confirmations"], 1)
assert_equal(tx2["confirmations"], 1)
# Node1's "from0" balance should be both transaction amounts:
- assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"]+tx2["amount"]))
+ assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"]))
else:
assert_equal(tx1["confirmations"], 0)
assert_equal(tx2["confirmations"], 0)
@@ -117,7 +124,7 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(tx1["confirmations"], -2)
assert_equal(tx2["confirmations"], -2)
- # Node0's total balance should be starting balance, plus 100BTC for
+ # Node0's total balance should be starting balance, plus 100BTC for
# two more matured blocks, minus 1240 for the double-spend, plus fees (which are
# negative):
expected = starting_balance + 100 - 1240 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee
@@ -128,18 +135,11 @@ class TxnMallTest(BitcoinTestFramework):
# fees (which are negative)
assert_equal(self.nodes[0].getbalance("foo"), 1219)
assert_equal(self.nodes[0].getbalance("bar"), 29)
- assert_equal(self.nodes[0].getbalance(""), starting_balance
- -1219
- - 29
- -1240
- + 100
- + fund_foo_tx["fee"]
- + fund_bar_tx["fee"]
- + doublespend_fee)
+ assert_equal(self.nodes[0].getbalance(""),
+ starting_balance - 1219 - 29 - 1240 + 100 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee)
# Node1's "from0" account balance should be just the doublespend:
assert_equal(self.nodes[1].getbalance("from0"), 1240)
if __name__ == '__main__':
TxnMallTest().main()
-
diff --git a/test/util/rpcauth-test.py b/test/util/rpcauth-test.py
index dfbb5ea3a7..2456feb102 100755
--- a/test/util/rpcauth-test.py
+++ b/test/util/rpcauth-test.py
@@ -28,16 +28,15 @@ class TestRPCAuth(unittest.TestCase):
self.assertGreaterEqual(len(self.rpcauth.generate_salt()), 16)
def test_generate_password(self):
- salt = self.rpcauth.generate_salt()
- password, password_hmac = self.rpcauth.generate_password(salt)
-
+ password = self.rpcauth.generate_password()
expected_password = base64.urlsafe_b64encode(
base64.urlsafe_b64decode(password)).decode('utf-8')
self.assertEqual(expected_password, password)
def test_check_password_hmac(self):
salt = self.rpcauth.generate_salt()
- password, password_hmac = self.rpcauth.generate_password(salt)
+ password = self.rpcauth.generate_password()
+ password_hmac = self.rpcauth.password_to_hmac(salt, password)
m = hmac.new(bytearray(salt, 'utf-8'),
bytearray(password, 'utf-8'), 'SHA256')