aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac8
-rw-r--r--doc/release-notes.md6
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/bitcoin-tx.cpp25
-rw-r--r--src/chainparams.cpp7
-rw-r--r--src/chainparams.h6
-rw-r--r--src/coins.cpp2
-rw-r--r--src/init.cpp16
-rw-r--r--src/memusage.h16
-rw-r--r--src/net_processing.cpp39
-rw-r--r--src/net_processing.h4
-rw-r--r--src/policy/rbf.h2
-rw-r--r--src/primitives/block.h5
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/random.cpp20
-rw-r--r--src/random.h6
-rw-r--r--src/rpc/blockchain.cpp9
-rw-r--r--src/rpc/client.cpp4
-rw-r--r--src/rpc/mining.cpp27
-rw-r--r--src/rpc/rawtransaction.cpp26
-rw-r--r--src/rpc/server.h2
-rw-r--r--src/test/DoS_tests.cpp4
-rw-r--r--src/test/blockencodings_tests.cpp10
-rw-r--r--src/test/bloom_tests.cpp2
-rw-r--r--src/test/checkqueue_tests.cpp10
-rw-r--r--src/test/coins_tests.cpp79
-rw-r--r--src/test/crypto_tests.cpp3
-rw-r--r--src/test/cuckoocache_tests.cpp24
-rw-r--r--src/test/dbwrapper_tests.cpp20
-rw-r--r--src/test/hash_tests.cpp2
-rw-r--r--src/test/merkle_tests.cpp5
-rw-r--r--src/test/miner_tests.cpp4
-rw-r--r--src/test/pmt_tests.cpp9
-rw-r--r--src/test/pow_tests.cpp6
-rw-r--r--src/test/prevector_tests.cpp67
-rw-r--r--src/test/random_tests.cpp7
-rw-r--r--src/test/scheduler_tests.cpp10
-rw-r--r--src/test/sighash_tests.cpp29
-rw-r--r--src/test/skiplist_tests.cpp46
-rw-r--r--src/test/test_bitcoin.cpp2
-rw-r--r--src/test/test_bitcoin.h21
-rw-r--r--src/test/test_random.h29
-rw-r--r--src/test/util_tests.cpp5
-rw-r--r--src/test/versionbits_tests.cpp13
-rw-r--r--src/validation.cpp111
-rw-r--r--src/validation.h44
-rw-r--r--src/versionbits.cpp2
-rw-r--r--src/versionbits.h4
-rw-r--r--src/wallet/db.cpp1
-rw-r--r--src/wallet/rpcwallet.cpp30
-rw-r--r--src/wallet/test/crypto_tests.cpp5
-rw-r--r--src/wallet/wallet.cpp10
-rw-r--r--src/wallet/wallet.h7
-rw-r--r--test/config.ini.in (renamed from test/functional/config.ini.in)2
-rwxr-xr-xtest/functional/bip68-sequence.py4
-rwxr-xr-xtest/functional/blockchain.py3
-rwxr-xr-xtest/functional/fundrawtransaction.py2
-rwxr-xr-xtest/functional/mempool_packages.py8
-rwxr-xr-xtest/functional/p2p-compactblocks.py2
-rwxr-xr-xtest/functional/p2p-segwit.py2
-rwxr-xr-xtest/functional/prioritise_transaction.py8
-rwxr-xr-xtest/functional/replace-by-fee.py27
-rwxr-xr-xtest/functional/test_runner.py2
-rw-r--r--test/util/bctest.py139
-rwxr-xr-xtest/util/bitcoin-util-test.py167
-rw-r--r--test/util/buildenv.py.in4
69 files changed, 679 insertions, 561 deletions
diff --git a/.gitignore b/.gitignore
index f1e9ca20c1..60c26dae8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,7 +80,6 @@ Bitcoin-Qt.app
# Unit-tests
Makefile.test
bitcoin-qt_test
-src/test/buildenv.py
# Resources cpp
qrc_*.cpp
@@ -101,8 +100,7 @@ coverage_percent.txt
linux-coverage-build
linux-build
win32-build
-test/functional/config.ini
-test/util/buildenv.py
+test/config.ini
test/cache/*
!src/leveldb*/Makefile
diff --git a/Makefile.am b/Makefile.am
index 3a56eea0c0..40114a551f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,7 +223,6 @@ dist_noinst_SCRIPTS = autogen.sh
EXTRA_DIST = $(top_srcdir)/share/genbuild.sh test/functional/test_runner.py test/functional $(DIST_CONTRIB) $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS)
EXTRA_DIST += \
- test/util/bctest.py \
test/util/bitcoin-util-test.py \
test/util/data/bitcoin-util-test.json \
test/util/data/blanktxv1.hex \
@@ -277,9 +276,6 @@ EXTRA_DIST += \
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
-# This file is problematic for out-of-tree builds if it exists.
-DISTCLEANFILES = test/util/buildenv.pyc
-
.INTERMEDIATE: $(COVERAGE_INFO)
DISTCHECK_CONFIGURE_FLAGS = --enable-man
diff --git a/configure.ac b/configure.ac
index ca66216554..160be397ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1161,13 +1161,11 @@ AC_SUBST(EVENT_PTHREADS_LIBS)
AC_SUBST(ZMQ_LIBS)
AC_SUBST(PROTOBUF_LIBS)
AC_SUBST(QR_LIBS)
-AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/functional/config.ini])
-AC_CONFIG_FILES([test/util/buildenv.py],[chmod +x test/util/buildenv.py])
+AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
AC_CONFIG_FILES([doc/Doxyfile])
AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py])
AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py])
-AC_CONFIG_LINKS([test/util/bctest.py:test/util/bctest.py])
dnl boost's m4 checks do something really nasty: they export these vars. As a
dnl result, they leak into secp256k1's configure and crazy things happen.
@@ -1215,8 +1213,8 @@ esac
dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows
case ${OS} in
*Windows*)
- sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/functional/config.ini > test/functional/config-2.ini
- mv test/functional/config-2.ini test/functional/config.ini
+ sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/config.ini > test/config-2.ini
+ mv test/config-2.ini test/config.ini
;;
esac
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 075c7c3911..a13ede2dd5 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -42,9 +42,15 @@ Low-level RPC changes
- The `gettxoutsetinfo` RPC reports `hash_serialized_2` instead of `hash_serialized`,
which does not commit to the transaction versions of unspent outputs, but does
commit to the height and coinbase information.
+ - The `gettxoutsetinfo` response now contains `disk_size` and `bogosize` instead of
+ `bytes_serialized`. The first is a more accurate estimate of actual disk usage, but
+ is not deterministic. The second is unrelated to disk usage, but is a
+ database-independent metric of UTXO set size: it counts every UTXO entry as 50 + the
+ length of its scriptPubKey.
- The `getutxos` REST path no longer reports the `txvers` field in JSON format,
and always reports 0 for transaction versions in the binary format
+
- Error codes have been updated to be more accurate for the following error cases:
- `getblock` now returns RPC_MISC_ERROR if the block can't be found on disk (for
example if the block has been pruned). Previously returned RPC_INTERNAL_ERROR.
diff --git a/src/Makefile.am b/src/Makefile.am
index ae2eb29c94..199d60b725 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -198,6 +198,7 @@ libbitcoin_server_a_SOURCES = \
noui.cpp \
policy/fees.cpp \
policy/policy.cpp \
+ policy/rbf.cpp \
pow.cpp \
rest.cpp \
rpc/blockchain.cpp \
@@ -240,7 +241,6 @@ libbitcoin_wallet_a_SOURCES = \
wallet/rpcwallet.cpp \
wallet/wallet.cpp \
wallet/walletdb.cpp \
- policy/rbf.cpp \
$(BITCOIN_CORE_H)
# crypto primitives library
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index ee1c11ff1f..13e0a03c76 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -74,7 +74,6 @@ BITCOIN_TESTS =\
test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/test_bitcoin_main.cpp \
- test/test_random.h \
test/testutil.cpp \
test/testutil.h \
test/timedata_tests.cpp \
@@ -148,7 +147,7 @@ bitcoin_test_clean : FORCE
check-local:
@echo "Running test/util/bitcoin-util-test.py..."
- $(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
+ $(top_builddir)/test/util/bitcoin-util-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index cf280f485c..367801dd78 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -13,6 +13,7 @@
#include "core_io.h"
#include "keystore.h"
#include "policy/policy.h"
+#include "policy/rbf.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "script/sign.h"
@@ -77,6 +78,7 @@ static int AppInitRawTx(int argc, char* argv[])
strUsage += HelpMessageOpt("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX"));
strUsage += HelpMessageOpt("locktime=N", _("Set TX lock time to N"));
strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
+ strUsage += HelpMessageOpt("rbfoptin(=N)", _("Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)"));
strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
strUsage += HelpMessageOpt("outpubkey=VALUE:PUBKEY[:FLAGS]", _("Add pay-to-pubkey output to TX") + ". " +
_("Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output") + ". " +
@@ -202,6 +204,26 @@ static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
tx.nLockTime = (unsigned int) newLocktime;
}
+static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInIdx)
+{
+ // parse requested index
+ int inIdx = atoi(strInIdx);
+ if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
+ throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
+ }
+
+ // set the nSequence to MAX_INT - 2 (= RBF opt in flag)
+ int cnt = 0;
+ for (CTxIn& txin : tx.vin) {
+ if (strInIdx == "" || cnt == inIdx) {
+ if (txin.nSequence > MAX_BIP125_RBF_SEQUENCE) {
+ txin.nSequence = MAX_BIP125_RBF_SEQUENCE;
+ }
+ }
+ ++cnt;
+ }
+}
+
static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)
{
std::vector<std::string> vStrInputParts;
@@ -649,6 +671,9 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command,
MutateTxVersion(tx, commandVal);
else if (command == "locktime")
MutateTxLocktime(tx, commandVal);
+ else if (command == "rbfoptin") {
+ MutateTxRBFOptIn(tx, commandVal);
+ }
else if (command == "delin")
MutateTxDelInput(tx, commandVal);
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 5055fb3e0a..04a2f680fa 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -55,7 +55,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}
-void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
consensus.vDeployments[d].nStartTime = nStartTime;
consensus.vDeployments[d].nTimeout = nTimeout;
@@ -356,8 +356,7 @@ void SelectParams(const std::string& network)
globalChainParams = CreateChainParams(network);
}
-void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
- globalChainParams->UpdateBIP9Parameters(d, nStartTime, nTimeout);
+ globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout);
}
-
diff --git a/src/chainparams.h b/src/chainparams.h
index e5312d1080..a2f136171b 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -76,7 +76,7 @@ public:
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
- void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
+ void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
protected:
CChainParams() {}
@@ -116,8 +116,8 @@ const CChainParams &Params();
void SelectParams(const std::string& chain);
/**
- * Allows modifying the BIP9 regtest parameters.
+ * Allows modifying the Version Bits regtest parameters.
*/
-void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
+void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/coins.cpp b/src/coins.cpp
index 5b7c562678..b45fc76338 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -86,7 +86,7 @@ void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight) {
const uint256& txid = tx.GetHash();
for (size_t i = 0; i < tx.vout.size(); ++i) {
// Pass fCoinbase as the possible_overwrite flag to AddCoin, in order to correctly
- // deal with the pre-BIP30 occurrances of duplicate coinbase transactions.
+ // deal with the pre-BIP30 occurrences of duplicate coinbase transactions.
cache.AddCoin(COutPoint(txid, i), Coin(tx.vout[i], nHeight, fCoinbase), fCoinbase);
}
}
diff --git a/src/init.cpp b/src/init.cpp
index 33023a1800..04d1280c92 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -449,7 +449,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT));
- strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified BIP9 deployment (regtest-only)");
+ strUsage += HelpMessageOpt("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)");
}
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + ListLogCategories() + ".");
@@ -1104,16 +1104,16 @@ bool AppInitParameterInteraction()
fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end());
}
- if (gArgs.IsArgSet("-bip9params")) {
- // Allow overriding BIP9 parameters for testing
+ if (gArgs.IsArgSet("-vbparams")) {
+ // Allow overriding version bits parameters for testing
if (!chainparams.MineBlocksOnDemand()) {
- return InitError("BIP9 parameters may only be overridden on regtest.");
+ return InitError("Version bits parameters may only be overridden on regtest.");
}
- for (const std::string& strDeployment : gArgs.GetArgs("-bip9params")) {
+ for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) {
std::vector<std::string> vDeploymentParams;
boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
if (vDeploymentParams.size() != 3) {
- return InitError("BIP9 parameters malformed, expecting deployment:start:end");
+ return InitError("Version bits parameters malformed, expecting deployment:start:end");
}
int64_t nStartTime, nTimeout;
if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
@@ -1126,9 +1126,9 @@ bool AppInitParameterInteraction()
for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
{
if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
- UpdateBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
+ UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
found = true;
- LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
+ LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
break;
}
}
diff --git a/src/memusage.h b/src/memusage.h
index b69acafffd..710120d285 100644
--- a/src/memusage.h
+++ b/src/memusage.h
@@ -16,8 +16,6 @@
#include <unordered_set>
#include <boost/foreach.hpp>
-#include <boost/unordered_set.hpp>
-#include <boost/unordered_map.hpp>
namespace memusage
{
@@ -148,8 +146,6 @@ static inline size_t DynamicUsage(const std::shared_ptr<X>& p)
return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0;
}
-// Boost data structures
-
template<typename X>
struct unordered_node : private X
{
@@ -158,18 +154,6 @@ private:
};
template<typename X, typename Y>
-static inline size_t DynamicUsage(const boost::unordered_set<X, Y>& s)
-{
- return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count());
-}
-
-template<typename X, typename Y, typename Z>
-static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m)
-{
- return MallocUsage(sizeof(unordered_node<std::pair<const X, Y> >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count());
-}
-
-template<typename X, typename Y>
static inline size_t DynamicUsage(const std::unordered_set<X, Y>& s)
{
return MallocUsage(sizeof(unordered_node<X>)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count());
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 971db3427c..4ca02c281d 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -168,6 +168,8 @@ struct CNodeState {
int nUnconnectingHeaders;
//! Whether we've started headers synchronization with this peer.
bool fSyncStarted;
+ //! When to potentially disconnect peer for stalling headers download
+ int64_t nHeadersSyncTimeout;
//! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince;
std::list<QueuedBlock> vBlocksInFlight;
@@ -207,6 +209,7 @@ struct CNodeState {
pindexBestHeaderSent = NULL;
nUnconnectingHeaders = 0;
fSyncStarted = false;
+ nHeadersSyncTimeout = 0;
nStallingSince = 0;
nDownloadingSince = 0;
nBlocksInFlight = 0;
@@ -481,7 +484,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
// Make sure pindexBestKnownBlock is up to date, we'll need it.
ProcessBlockAvailability(nodeid);
- if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork) {
+ if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) {
// This peer has nothing interesting.
return;
}
@@ -2881,6 +2884,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// Only actively request headers from a single peer, unless we're close to today.
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
state.fSyncStarted = true;
+ state.nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(consensusParams.nPowTargetSpacing);
nSyncStarted++;
const CBlockIndex *pindexStart = pindexBestHeader;
/* If possible, start at the block preceding the currently
@@ -3204,6 +3208,39 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
return true;
}
}
+ // Check for headers sync timeouts
+ if (state.fSyncStarted && state.nHeadersSyncTimeout < std::numeric_limits<int64_t>::max()) {
+ // Detect whether this is a stalling initial-headers-sync peer
+ if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - 24*60*60) {
+ if (nNow > state.nHeadersSyncTimeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
+ // Disconnect a (non-whitelisted) peer if it is our only sync peer,
+ // and we have others we could be using instead.
+ // Note: If all our peers are inbound, then we won't
+ // disconnect our sync peer for stalling; we have bigger
+ // problems if we can't get any outbound peers.
+ if (!pto->fWhitelisted) {
+ LogPrintf("Timeout downloading headers from peer=%d, disconnecting\n", pto->GetId());
+ pto->fDisconnect = true;
+ return true;
+ } else {
+ LogPrintf("Timeout downloading headers from whitelisted peer=%d, not disconnecting\n", pto->GetId());
+ // Reset the headers sync state so that we have a
+ // chance to try downloading from a different peer.
+ // Note: this will also result in at least one more
+ // getheaders message to be sent to
+ // this peer (eventually).
+ state.fSyncStarted = false;
+ nSyncStarted--;
+ state.nHeadersSyncTimeout = 0;
+ }
+ }
+ } else {
+ // After we've caught up once, reset the timeout so we can't trigger
+ // disconnect later.
+ state.nHeadersSyncTimeout = std::numeric_limits<int64_t>::max();
+ }
+ }
+
//
// Message: getdata (blocks)
diff --git a/src/net_processing.h b/src/net_processing.h
index f460595bc1..db6d81e6b6 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -17,6 +17,10 @@ static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
/** Default number of orphan+recently-replaced txn to keep around for block reconstruction */
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
+/** Headers download timeout expressed in microseconds
+ * Timeout = base + per_header * (expected number of headers) */
+static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
+static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 139aec5760..22c73f3319 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -7,6 +7,8 @@
#include "txmempool.h"
+static const uint32_t MAX_BIP125_RBF_SEQUENCE = 0xfffffffd;
+
enum RBFTransactionState {
RBF_TRANSACTIONSTATE_UNKNOWN,
RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125,
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 4c6eb20ad5..f03cf48504 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -129,10 +129,7 @@ struct CBlockLocator
CBlockLocator() {}
- CBlockLocator(const std::vector<uint256>& vHaveIn)
- {
- vHave = vHaveIn;
- }
+ CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
ADD_SERIALIZE_METHODS;
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 28d1d0eeb4..6cd246ed53 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -151,11 +151,7 @@ CInv::CInv()
hash.SetNull();
}
-CInv::CInv(int typeIn, const uint256& hashIn)
-{
- type = typeIn;
- hash = hashIn;
-}
+CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
bool operator<(const CInv& a, const CInv& b)
{
diff --git a/src/random.cpp b/src/random.cpp
index de7553c825..e1ccfa5f24 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -304,6 +304,26 @@ void FastRandomContext::RandomSeed()
requires_seed = false;
}
+uint256 FastRandomContext::rand256()
+{
+ if (bytebuf_size < 32) {
+ FillByteBuffer();
+ }
+ uint256 ret;
+ memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32);
+ bytebuf_size -= 32;
+ return ret;
+}
+
+std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
+{
+ std::vector<unsigned char> ret(len);
+ if (len > 0) {
+ rng.Output(&ret[0], len);
+ }
+ return ret;
+}
+
FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
rng.SetKey(seed.begin(), 32);
diff --git a/src/random.h b/src/random.h
index 6a63d57429..dcb74eadb5 100644
--- a/src/random.h
+++ b/src/random.h
@@ -110,9 +110,15 @@ public:
}
}
+ /** Generate random bytes. */
+ std::vector<unsigned char> randbytes(size_t len);
+
/** Generate a random 32-bit integer. */
uint32_t rand32() { return randbits(32); }
+ /** generate a random uint256. */
+ uint256 rand256();
+
/** Generate a random boolean. */
bool randbool() { return randbits(1); }
};
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 96871ce1dc..b66c1c2b64 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -781,11 +781,12 @@ struct CCoinsStats
uint256 hashBlock;
uint64_t nTransactions;
uint64_t nTransactionOutputs;
+ uint64_t nBogoSize;
uint256 hashSerialized;
uint64_t nDiskSize;
CAmount nTotalAmount;
- CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nTotalAmount(0) {}
+ CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), nDiskSize(0), nTotalAmount(0) {}
};
static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
@@ -800,6 +801,8 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash,
ss << VARINT(output.second.out.nValue);
stats.nTransactionOutputs++;
stats.nTotalAmount += output.second.out.nValue;
+ stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
+ 2 /* scriptPubKey len */ + output.second.out.scriptPubKey.size() /* scriptPubKey */;
}
ss << VARINT(0);
}
@@ -904,7 +907,8 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
" \"bestblock\": \"hex\", (string) the best block hash hex\n"
" \"transactions\": n, (numeric) The number of transactions\n"
" \"txouts\": n, (numeric) The number of output transactions\n"
- " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
+ " \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n"
+ " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n"
" \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n"
" \"total_amount\": x.xxx (numeric) The total amount\n"
"}\n"
@@ -922,6 +926,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
+ ret.push_back(Pair("bogosize", (int64_t)stats.nBogoSize));
ret.push_back(Pair("hash_serialized_2", stats.hashSerialized.GetHex()));
ret.push_back(Pair("disk_size", stats.nDiskSize));
ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index a3a692c14d..8dd84e20c9 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -86,6 +86,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" },
+ { "createrawtransaction", 3, "optintorbf" },
{ "signrawtransaction", 1, "prevtxs" },
{ "signrawtransaction", 2, "privkeys" },
{ "sendrawtransaction", 1, "allowhighfees" },
@@ -112,7 +113,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "estimaterawfee", 0, "nblocks" },
{ "estimaterawfee", 1, "threshold" },
{ "estimaterawfee", 2, "horizon" },
- { "prioritisetransaction", 1, "fee_delta" },
+ { "prioritisetransaction", 1, "priority_delta" },
+ { "prioritisetransaction", 2, "fee_delta" },
{ "setban", 2, "bantime" },
{ "setban", 3, "absolute" },
{ "setnetworkactive", 0, "state" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index d744269df1..cfe42ec7d8 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -257,26 +257,31 @@ 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)
{
- if (request.fHelp || request.params.size() != 2)
+ if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
- "prioritisetransaction <txid> <fee delta>\n"
+ "prioritisetransaction <txid> <priority delta> <fee delta>\n"
"Accepts the transaction into mined blocks at a higher (or lower) priority\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id.\n"
- "2. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
+ "2. priority_delta (numeric, optional) Fee-independent priority adjustment. Not supported, so must be zero or null.\n"
+ "3. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
" The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
" considers the transaction as it would have paid a higher (or lower) fee.\n"
"\nResult:\n"
"true (boolean) Returns true\n"
"\nExamples:\n"
- + HelpExampleCli("prioritisetransaction", "\"txid\" 10000")
- + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000")
+ + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
+ + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
);
LOCK(cs_main);
uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
- CAmount nAmount = request.params[1].get_int64();
+ CAmount nAmount = request.params[2].get_int64();
+
+ if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is not supported, and adjustment thereof must be zero.");
+ }
mempool.PrioritiseTransaction(hash, nAmount);
return true;
@@ -303,7 +308,7 @@ static UniValue BIP22ValidationResult(const CValidationState& state)
}
std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
- const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
+ const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
std::string s = vbinfo.name;
if (!vbinfo.gbt_force) {
s.insert(s.begin(), '!');
@@ -515,7 +520,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
}
- const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
+ const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT];
// If the caller is indicating segwit support, then allow CreateNewBlock()
// to select witness transactions, after segwit activates (otherwise
// don't).
@@ -629,7 +634,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
// FALL THROUGH to get vbavailable set...
case THRESHOLD_STARTED:
{
- const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
+ const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
if (!vbinfo.gbt_force) {
@@ -642,7 +647,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
case THRESHOLD_ACTIVE:
{
// Add to rules only
- const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
+ const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
aRules.push_back(gbt_vb_name(pos));
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
// Not supported by the client; make sure it's safe to proceed
@@ -959,7 +964,7 @@ static const CRPCCommand commands[] =
// --------------------- ------------------------ ----------------------- ----------
{ "mining", "getnetworkhashps", &getnetworkhashps, true, {"nblocks","height"} },
{ "mining", "getmininginfo", &getmininginfo, true, {} },
- { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","fee_delta"} },
+ { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","priority_delta","fee_delta"} },
{ "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} },
{ "mining", "submitblock", &submitblock, true, {"hexdata","parameters"} },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index e27c2a77c7..00ddd9d16f 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -14,6 +14,7 @@
#include "merkleblock.h"
#include "net.h"
#include "policy/policy.h"
+#include "policy/rbf.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
#include "script/script.h"
@@ -289,9 +290,9 @@ UniValue verifytxoutproof(const JSONRPCRequest& request)
UniValue createrawtransaction(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
+ if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
- "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n"
+ "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime ) ( optintorbf )\n"
"\nCreate a transaction spending the given inputs and creating new outputs.\n"
"Outputs can be addresses or data.\n"
"Returns hex-encoded raw transaction.\n"
@@ -315,6 +316,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
" ,...\n"
" }\n"
"3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
+ "4. optintorbf (boolean, optional, default=false) Allow this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible.\n"
"\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n"
@@ -341,6 +343,8 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
rawTx.nLockTime = nLockTime;
}
+ bool rbfOptIn = request.params.size() > 3 ? request.params[3].isTrue() : false;
+
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
@@ -354,16 +358,24 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
if (nOutput < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
- uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits<uint32_t>::max() - 1 : std::numeric_limits<uint32_t>::max());
+ uint32_t nSequence;
+ if (rbfOptIn) {
+ nSequence = MAX_BIP125_RBF_SEQUENCE;
+ } else if (rawTx.nLockTime) {
+ nSequence = std::numeric_limits<uint32_t>::max() - 1;
+ } else {
+ nSequence = std::numeric_limits<uint32_t>::max();
+ }
// set the sequence number if passed in the parameters object
const UniValue& sequenceObj = find_value(o, "sequence");
if (sequenceObj.isNum()) {
int64_t seqNr64 = sequenceObj.get_int64();
- if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max())
+ if (seqNr64 < 0 || seqNr64 > std::numeric_limits<uint32_t>::max()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
- else
+ } else {
nSequence = (uint32_t)seqNr64;
+ }
}
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
@@ -397,6 +409,10 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
}
}
+ if (request.params.size() > 3 && rbfOptIn != SignalsOptInRBF(rawTx)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict optintorbf option");
+ }
+
return EncodeHexTx(rawTx);
}
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 1e984cbc0d..a893f49033 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -50,7 +50,7 @@ public:
std::string URI;
std::string authUser;
- JSONRPCRequest() { id = NullUniValue; params = NullUniValue; fHelp = false; }
+ JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
void parse(const UniValue& valRequest);
};
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index e6b45a3b5e..a7a3a1bdf0 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CTransactionRef RandomOrphan()
{
std::map<uint256, COrphanTx>::iterator it;
- it = mapOrphanTransactions.lower_bound(GetRandHash());
+ it = mapOrphanTransactions.lower_bound(InsecureRand256());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
return it->second.tx;
@@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
- tx.vin[0].prevout.hash = GetRandHash();
+ tx.vin[0].prevout.hash = InsecureRand256();
tx.vin[0].scriptSig << OP_1;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 9e4a56919d..10a40fea3c 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -30,16 +30,16 @@ static CBlock BuildBlockTestCase() {
block.vtx.resize(3);
block.vtx[0] = MakeTransactionRef(tx);
block.nVersion = 42;
- block.hashPrevBlock = GetRandHash();
+ block.hashPrevBlock = InsecureRand256();
block.nBits = 0x207fffff;
- tx.vin[0].prevout.hash = GetRandHash();
+ tx.vin[0].prevout.hash = InsecureRand256();
tx.vin[0].prevout.n = 0;
block.vtx[1] = MakeTransactionRef(tx);
tx.vin.resize(10);
for (size_t i = 0; i < tx.vin.size(); i++) {
- tx.vin[i].prevout.hash = GetRandHash();
+ tx.vin[i].prevout.hash = InsecureRand256();
tx.vin[i].prevout.n = 0;
}
block.vtx[2] = MakeTransactionRef(tx);
@@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
block.vtx.resize(1);
block.vtx[0] = MakeTransactionRef(std::move(coinbase));
block.nVersion = 42;
- block.hashPrevBlock = GetRandHash();
+ block.hashPrevBlock = InsecureRand256();
block.nBits = 0x207fffff;
bool mutated;
@@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
BlockTransactionsRequest req1;
- req1.blockhash = GetRandHash();
+ req1.blockhash = InsecureRand256();
req1.indexes.resize(4);
req1.indexes[0] = 0;
req1.indexes[1] = 1;
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 27bc92d670..1788ee1326 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none)
static std::vector<unsigned char> RandomData()
{
- uint256 r = GetRandHash();
+ uint256 r = InsecureRand256();
return std::vector<unsigned char>(r.begin(), r.end());
}
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 287395c6c6..bf999eb524 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -160,7 +160,7 @@ void Correct_Queue_range(std::vector<size_t> range)
FakeCheckCheckCompletion::n_calls = 0;
CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get());
while (total) {
- vChecks.resize(std::min(total, (size_t) GetRand(10)));
+ vChecks.resize(std::min(total, (size_t) InsecureRandRange(10)));
total -= vChecks.size();
control.Add(vChecks);
}
@@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random)
{
std::vector<size_t> range;
range.reserve(100000/1000);
- for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)GetRand(std::min((size_t)1000, ((size_t)100000) - i))))
+ for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min((size_t)1000, ((size_t)100000) - i))))
range.push_back(i);
Correct_Queue_range(range);
}
@@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure)
CCheckQueueControl<FailingCheck> control(fail_queue.get());
size_t remaining = i;
while (remaining) {
- size_t r = GetRand(10);
+ size_t r = InsecureRandRange(10);
std::vector<FailingCheck> vChecks;
vChecks.reserve(r);
@@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)
{
CCheckQueueControl<UniqueCheck> control(queue.get());
while (total) {
- size_t r = GetRand(10);
+ size_t r = InsecureRandRange(10);
std::vector<UniqueCheck> vChecks;
for (size_t k = 0; k < r && total; k++)
vChecks.emplace_back(--total);
@@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)
{
CCheckQueueControl<MemoryCheck> control(queue.get());
while (total) {
- size_t r = GetRand(10);
+ size_t r = InsecureRandRange(10);
std::vector<MemoryCheck> vChecks;
for (size_t k = 0; k < r && total; k++) {
total--;
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 0ed71b96fc..a72975d6e4 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -8,7 +8,6 @@
#include "undo.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include "validation.h"
#include "consensus/validation.h"
@@ -44,7 +43,7 @@ public:
return false;
}
coin = it->second;
- if (coin.IsSpent() && insecure_rand() % 2 == 0) {
+ if (coin.IsSpent() && InsecureRandBool() == 0) {
// Randomly return false in case of an empty entry.
return false;
}
@@ -65,7 +64,7 @@ public:
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
// Same optimization used in CCoinsViewDB is to only write dirty entries.
map_[it->first] = it->second.coin;
- if (it->second.coin.IsSpent() && insecure_rand() % 3 == 0) {
+ if (it->second.coin.IsSpent() && InsecureRandRange(3) == 0) {
// Randomly delete empty entries on write.
map_.erase(it->first);
}
@@ -140,31 +139,31 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
std::vector<uint256> txids;
txids.resize(NUM_SIMULATION_ITERATIONS / 8);
for (unsigned int i = 0; i < txids.size(); i++) {
- txids[i] = GetRandHash();
+ txids[i] = InsecureRand256();
}
for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
// Do a random modification.
{
- uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration.
+ uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration.
Coin& coin = result[COutPoint(txid, 0)];
- const Coin& entry = (insecure_rand() % 500 == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
+ const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
BOOST_CHECK(coin == entry);
- if (insecure_rand() % 5 == 0 || coin.IsSpent()) {
+ if (InsecureRandRange(5) == 0 || coin.IsSpent()) {
Coin newcoin;
- newcoin.out.nValue = insecure_rand();
+ newcoin.out.nValue = InsecureRand32();
newcoin.nHeight = 1;
- if (insecure_rand() % 16 == 0 && coin.IsSpent()) {
- newcoin.out.scriptPubKey.assign(1 + (insecure_rand() & 0x3F), OP_RETURN);
+ if (InsecureRandRange(16) == 0 && coin.IsSpent()) {
+ newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN);
BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
added_an_unspendable_entry = true;
} else {
- newcoin.out.scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting
+ newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0); // Random sizes so we can test memory usage accounting
(coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
coin = newcoin;
}
- stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || insecure_rand() & 1);
+ stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || InsecureRand32() & 1);
} else {
removed_an_entry = true;
coin.Clear();
@@ -173,15 +172,15 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
}
// One every 10 iterations, remove a random entry from the cache
- if (insecure_rand() % 10 == 0) {
- COutPoint out(txids[insecure_rand() % txids.size()], 0);
- int cacheid = insecure_rand() % stack.size();
+ if (InsecureRandRange(10) == 0) {
+ COutPoint out(txids[InsecureRand32() % txids.size()], 0);
+ int cacheid = InsecureRand32() % stack.size();
stack[cacheid]->Uncache(out);
uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out);
}
// Once every 1000 iterations and at the end, verify the full cache.
- if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
for (auto it = result.begin(); it != result.end(); it++) {
bool have = stack.back()->HaveCoin(it->first);
const Coin& coin = stack.back()->AccessCoin(it->first);
@@ -199,22 +198,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
}
}
- if (insecure_rand() % 100 == 0) {
+ if (InsecureRandRange(100) == 0) {
// Every 100 iterations, flush an intermediate cache
- if (stack.size() > 1 && insecure_rand() % 2 == 0) {
- unsigned int flushIndex = insecure_rand() % (stack.size() - 1);
+ if (stack.size() > 1 && InsecureRandBool() == 0) {
+ unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
stack[flushIndex]->Flush();
}
}
- if (insecure_rand() % 100 == 0) {
+ if (InsecureRandRange(100) == 0) {
// Every 100 iterations, change the cache stack.
- if (stack.size() > 0 && insecure_rand() % 2 == 0) {
+ if (stack.size() > 0 && InsecureRandBool() == 0) {
//Remove the top cache
stack.back()->Flush();
delete stack.back();
stack.pop_back();
}
- if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) {
+ if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
//Add a new cache
CCoinsView* tip = &base;
if (stack.size() > 0) {
@@ -254,7 +253,7 @@ UtxoData utxoData;
UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
assert(utxoSet.size());
- auto utxoSetIt = utxoSet.lower_bound(COutPoint(GetRandHash(), 0));
+ auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0));
if (utxoSetIt == utxoSet.end()) {
utxoSetIt = utxoSet.begin();
}
@@ -287,7 +286,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
std::set<COutPoint> utxoset;
for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
- uint32_t randiter = insecure_rand();
+ uint32_t randiter = InsecureRand32();
// 19/20 txs add a new transaction
if (randiter % 20 < 19) {
@@ -295,14 +294,14 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
tx.vin.resize(1);
tx.vout.resize(1);
tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate
- tx.vout[0].scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting
- unsigned int height = insecure_rand();
+ tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting
+ unsigned int height = InsecureRand32();
Coin old_coin;
// 2/20 times create a new coinbase
if (randiter % 20 < 2 || coinbase_coins.size() < 10) {
// 1/10 of those times create a duplicate coinbase
- if (insecure_rand() % 10 == 0 && coinbase_coins.size()) {
+ if (InsecureRandRange(10) == 0 && coinbase_coins.size()) {
auto utxod = FindRandomFrom(coinbase_coins);
// Reuse the exact same coinbase
tx = std::get<0>(utxod->second);
@@ -412,7 +411,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
}
// Once every 1000 iterations and at the end, verify the full cache.
- if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
for (auto it = result.begin(); it != result.end(); it++) {
bool have = stack.back()->HaveCoin(it->first);
const Coin& coin = stack.back()->AccessCoin(it->first);
@@ -422,31 +421,31 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
}
// One every 10 iterations, remove a random entry from the cache
- if (utxoset.size() > 1 && insecure_rand() % 30 == 0) {
- stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first);
+ if (utxoset.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first);
}
- if (disconnected_coins.size() > 1 && insecure_rand() % 30 == 0) {
- stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first);
+ if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first);
}
- if (duplicate_coins.size() > 1 && insecure_rand() % 30 == 0) {
- stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first);
+ if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first);
}
- if (insecure_rand() % 100 == 0) {
+ if (InsecureRandRange(100) == 0) {
// Every 100 iterations, flush an intermediate cache
- if (stack.size() > 1 && insecure_rand() % 2 == 0) {
- unsigned int flushIndex = insecure_rand() % (stack.size() - 1);
+ if (stack.size() > 1 && InsecureRandBool() == 0) {
+ unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
stack[flushIndex]->Flush();
}
}
- if (insecure_rand() % 100 == 0) {
+ if (InsecureRandRange(100) == 0) {
// Every 100 iterations, change the cache stack.
- if (stack.size() > 0 && insecure_rand() % 2 == 0) {
+ if (stack.size() > 0 && InsecureRandBool() == 0) {
stack.back()->Flush();
delete stack.back();
stack.pop_back();
}
- if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) {
+ if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
CCoinsView* tip = &base;
if (stack.size() > 0) {
tip = stack.back();
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 72e562808a..a4f0e17c99 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -13,7 +13,6 @@
#include "random.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <vector>
@@ -39,7 +38,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) {
Hasher hasher(h);
size_t pos = 0;
while (pos < in.size()) {
- size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1);
+ size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1);
hasher.Write((unsigned char*)&in[pos], len);
pos += len;
if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) {
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index 8cae4e66e8..ed391e184c 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -23,18 +23,18 @@
* using BOOST_CHECK_CLOSE to fail.
*
*/
-FastRandomContext insecure_rand(true);
+FastRandomContext local_rand_ctx(true);
BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
-/** insecure_GetRandHash fills in a uint256 from insecure_rand
+/** insecure_GetRandHash fills in a uint256 from local_rand_ctx
*/
void insecure_GetRandHash(uint256& t)
{
uint32_t* ptr = (uint32_t*)t.begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = insecure_rand.rand32();
+ *(ptr++) = local_rand_ctx.rand32();
}
@@ -45,7 +45,7 @@ void insecure_GetRandHash(uint256& t)
*/
BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
{
- insecure_rand = FastRandomContext(true);
+ local_rand_ctx = FastRandomContext(true);
CuckooCache::cache<uint256, SignatureCacheHasher> cc{};
size_t megabytes = 4;
cc.setup_bytes(megabytes << 20);
@@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
template <typename Cache>
double test_cache(size_t megabytes, double load)
{
- insecure_rand = FastRandomContext(true);
+ local_rand_ctx = FastRandomContext(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -76,7 +76,7 @@ double test_cache(size_t megabytes, double load)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = insecure_rand.rand32();
+ *(ptr++) = local_rand_ctx.rand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -137,7 +137,7 @@ template <typename Cache>
void test_cache_erase(size_t megabytes)
{
double load = 1;
- insecure_rand = FastRandomContext(true);
+ local_rand_ctx = FastRandomContext(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -147,7 +147,7 @@ void test_cache_erase(size_t megabytes)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = insecure_rand.rand32();
+ *(ptr++) = local_rand_ctx.rand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -200,7 +200,7 @@ template <typename Cache>
void test_cache_erase_parallel(size_t megabytes)
{
double load = 1;
- insecure_rand = FastRandomContext(true);
+ local_rand_ctx = FastRandomContext(true);
std::vector<uint256> hashes;
Cache set{};
size_t bytes = megabytes * (1 << 20);
@@ -210,7 +210,7 @@ void test_cache_erase_parallel(size_t megabytes)
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)hashes[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = insecure_rand.rand32();
+ *(ptr++) = local_rand_ctx.rand32();
}
/** We make a copy of the hashes because future optimizations of the
* cuckoocache may overwrite the inserted element, so the test is
@@ -302,7 +302,7 @@ void test_cache_generations()
// iterations with non-deterministic values, so it isn't "overfit" to the
// specific entropy in FastRandomContext(true) and implementation of the
// cache.
- insecure_rand = FastRandomContext(true);
+ local_rand_ctx = FastRandomContext(true);
// block_activity models a chunk of network activity. n_insert elements are
// adde to the cache. The first and last n/4 are stored for removal later
@@ -319,7 +319,7 @@ void test_cache_generations()
for (uint32_t i = 0; i < n_insert; ++i) {
uint32_t* ptr = (uint32_t*)inserts[i].begin();
for (uint8_t j = 0; j < 8; ++j)
- *(ptr++) = insecure_rand.rand32();
+ *(ptr++) = local_rand_ctx.rand32();
}
for (uint32_t i = 0; i < n_insert / 4; ++i)
reads.push_back(inserts[i]);
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index c9d9849ada..2d8a419bdb 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
fs::path ph = fs::temp_directory_path() / fs::unique_path();
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
char key = 'k';
- uint256 in = GetRandHash();
+ uint256 in = InsecureRand256();
uint256 res;
// Ensure that we're doing real obfuscation when obfuscate=true
@@ -53,11 +53,11 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
char key = 'i';
- uint256 in = GetRandHash();
+ uint256 in = InsecureRand256();
char key2 = 'j';
- uint256 in2 = GetRandHash();
+ uint256 in2 = InsecureRand256();
char key3 = 'k';
- uint256 in3 = GetRandHash();
+ uint256 in3 = InsecureRand256();
uint256 res;
CDBBatch batch(dbw);
@@ -91,10 +91,10 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
// The two keys are intentionally chosen for ordering
char key = 'j';
- uint256 in = GetRandHash();
+ uint256 in = InsecureRand256();
BOOST_CHECK(dbw.Write(key, in));
char key2 = 'k';
- uint256 in2 = GetRandHash();
+ uint256 in2 = InsecureRand256();
BOOST_CHECK(dbw.Write(key2, in2));
std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
@@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
// Set up a non-obfuscated wrapper to write some initial data.
CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
char key = 'k';
- uint256 in = GetRandHash();
+ uint256 in = InsecureRand256();
uint256 res;
BOOST_CHECK(dbw->Write(key, in));
@@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string
- uint256 in2 = GetRandHash();
+ uint256 in2 = InsecureRand256();
uint256 res3;
// Check that we can write successfully
@@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
// Set up a non-obfuscated wrapper to write some initial data.
CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
char key = 'k';
- uint256 in = GetRandHash();
+ uint256 in = InsecureRand256();
uint256 res;
BOOST_CHECK(dbw->Write(key, in));
@@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
BOOST_CHECK(!odbw.Read(key, res2));
BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw)));
- uint256 in2 = GetRandHash();
+ uint256 in2 = InsecureRand256();
uint256 res3;
// Check that we can write successfully
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index bb7e473248..05b6b3b1e6 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(siphash)
for (int i = 0; i < 16; ++i) {
uint64_t k1 = ctx.rand64();
uint64_t k2 = ctx.rand64();
- uint256 x = GetRandHash();
+ uint256 x = InsecureRand256();
uint32_t n = ctx.rand32();
uint8_t nb[4];
WriteLE32(nb, n);
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index f2f06fa8e2..1a1cf4399c 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -4,7 +4,6 @@
#include "consensus/merkle.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <boost/test/unit_test.hpp>
@@ -68,7 +67,7 @@ BOOST_AUTO_TEST_CASE(merkle_test)
{
for (int i = 0; i < 32; i++) {
// Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes.
- int ntx = (i <= 16) ? i : 17 + (insecure_rand() % 4000);
+ int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000));
// Try up to 3 mutations.
for (int mutate = 0; mutate <= 3; mutate++) {
int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first.
@@ -121,7 +120,7 @@ BOOST_AUTO_TEST_CASE(merkle_test)
// If ntx <= 16, try all branches. Otherwise, try 16 random ones.
int mtx = loop;
if (ntx > 16) {
- mtx = insecure_rand() % ntx;
+ mtx = InsecureRandRange(ntx);
}
std::vector<uint256> newBranch = BlockMerkleBranch(block, mtx);
std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx);
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index a40060e657..c95800a728 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -372,7 +372,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
while (chainActive.Tip()->nHeight < 209999) {
CBlockIndex* prev = chainActive.Tip();
CBlockIndex* next = new CBlockIndex();
- next->phashBlock = new uint256(GetRandHash());
+ next->phashBlock = new uint256(InsecureRand256());
pcoinsTip->SetBestBlock(next->GetBlockHash());
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
@@ -384,7 +384,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
while (chainActive.Tip()->nHeight < 210000) {
CBlockIndex* prev = chainActive.Tip();
CBlockIndex* next = new CBlockIndex();
- next->phashBlock = new uint256(GetRandHash());
+ next->phashBlock = new uint256(InsecureRand256());
pcoinsTip->SetBestBlock(next->GetBlockHash());
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index a1cb32019a..708a9ca508 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -10,7 +10,6 @@
#include "arith_uint256.h"
#include "version.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <vector>
@@ -22,8 +21,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree
public:
// flip one bit in one of the hashes - this should break the authentication
void Damage() {
- unsigned int n = insecure_rand() % vHash.size();
- int bit = insecure_rand() % 256;
+ unsigned int n = InsecureRandRange(vHash.size());
+ int bit = InsecureRandBits(8);
*(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7);
}
};
@@ -32,7 +31,7 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(pmt_test1)
{
- seed_insecure_rand(false);
+ SeedInsecureRand(false);
static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095};
for (int i = 0; i < 12; i++) {
@@ -63,7 +62,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
std::vector<bool> vMatch(nTx, false);
std::vector<uint256> vMatchTxid1;
for (unsigned int j=0; j<nTx; j++) {
- bool fInclude = (insecure_rand() & ((1 << (att/2)) - 1)) == 0;
+ bool fInclude = InsecureRandBits(att / 2) == 0;
vMatch[j] = fInclude;
if (fInclude)
vMatchTxid1.push_back(vTxid[j]);
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 3b79f8000d..b9fabd02e4 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -74,9 +74,9 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
}
for (int j = 0; j < 1000; j++) {
- CBlockIndex *p1 = &blocks[GetRand(10000)];
- CBlockIndex *p2 = &blocks[GetRand(10000)];
- CBlockIndex *p3 = &blocks[GetRand(10000)];
+ CBlockIndex *p1 = &blocks[InsecureRandRange(10000)];
+ CBlockIndex *p2 = &blocks[InsecureRandRange(10000)];
+ CBlockIndex *p3 = &blocks[InsecureRandRange(10000)];
int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus());
BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index cfed5e347e..354fed1c1d 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -9,7 +9,6 @@
#include "streams.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <boost/test/unit_test.hpp>
@@ -188,7 +187,7 @@ public:
}
prevector_tester() {
- seed_insecure_rand();
+ SeedInsecureRand();
rand_seed = insecure_rand_seed;
rand_cache = insecure_rand_ctx;
}
@@ -199,67 +198,65 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt)
for (int j = 0; j < 64; j++) {
prevector_tester<8, int> test;
for (int i = 0; i < 2048; i++) {
- int r = insecure_rand();
- if ((r % 4) == 0) {
- test.insert(insecure_rand() % (test.size() + 1), insecure_rand());
+ if (InsecureRandBits(2) == 0) {
+ test.insert(InsecureRandRange(test.size() + 1), InsecureRand32());
}
- if (test.size() > 0 && ((r >> 2) % 4) == 1) {
- test.erase(insecure_rand() % test.size());
+ if (test.size() > 0 && InsecureRandBits(2) == 1) {
+ test.erase(InsecureRandRange(test.size()));
}
- if (((r >> 4) % 8) == 2) {
- int new_size = std::max<int>(0, std::min<int>(30, test.size() + (insecure_rand() % 5) - 2));
+ if (InsecureRandBits(3) == 2) {
+ int new_size = std::max<int>(0, std::min<int>(30, test.size() + (InsecureRandRange(5)) - 2));
test.resize(new_size);
}
- if (((r >> 7) % 8) == 3) {
- test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_rand() % 2), insecure_rand());
+ if (InsecureRandBits(3) == 3) {
+ test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), InsecureRand32());
}
- if (((r >> 10) % 8) == 4) {
- int del = std::min<int>(test.size(), 1 + (insecure_rand() % 2));
- int beg = insecure_rand() % (test.size() + 1 - del);
+ if (InsecureRandBits(3) == 4) {
+ int del = std::min<int>(test.size(), 1 + (InsecureRandBool()));
+ int beg = InsecureRandRange(test.size() + 1 - del);
test.erase(beg, beg + del);
}
- if (((r >> 13) % 16) == 5) {
- test.push_back(insecure_rand());
+ if (InsecureRandBits(4) == 5) {
+ test.push_back(InsecureRand32());
}
- if (test.size() > 0 && ((r >> 17) % 16) == 6) {
+ if (test.size() > 0 && InsecureRandBits(4) == 6) {
test.pop_back();
}
- if (((r >> 21) % 32) == 7) {
+ if (InsecureRandBits(5) == 7) {
int values[4];
- int num = 1 + (insecure_rand() % 4);
+ int num = 1 + (InsecureRandBits(2));
for (int k = 0; k < num; k++) {
- values[k] = insecure_rand();
+ values[k] = InsecureRand32();
}
- test.insert_range(insecure_rand() % (test.size() + 1), values, values + num);
+ test.insert_range(InsecureRandRange(test.size() + 1), values, values + num);
}
- if (((r >> 26) % 32) == 8) {
- int del = std::min<int>(test.size(), 1 + (insecure_rand() % 4));
- int beg = insecure_rand() % (test.size() + 1 - del);
+ if (InsecureRandBits(5) == 8) {
+ int del = std::min<int>(test.size(), 1 + (InsecureRandBits(2)));
+ int beg = InsecureRandRange(test.size() + 1 - del);
test.erase(beg, beg + del);
}
- r = insecure_rand();
- if (r % 32 == 9) {
- test.reserve(insecure_rand() % 32);
+ if (InsecureRandBits(5) == 9) {
+ test.reserve(InsecureRandBits(5));
}
- if ((r >> 5) % 64 == 10) {
+ if (InsecureRandBits(6) == 10) {
test.shrink_to_fit();
}
if (test.size() > 0) {
- test.update(insecure_rand() % test.size(), insecure_rand());
+ test.update(InsecureRandRange(test.size()), InsecureRand32());
}
- if (((r >> 11) % 1024) == 11) {
+ if (InsecureRandBits(10) == 11) {
test.clear();
}
- if (((r >> 21) % 512) == 12) {
- test.assign(insecure_rand() % 32, insecure_rand());
+ if (InsecureRandBits(9) == 12) {
+ test.assign(InsecureRandBits(5), InsecureRand32());
}
- if (((r >> 15) % 8) == 3) {
+ if (InsecureRandBits(3) == 3) {
test.swap();
}
- if (((r >> 15) % 16) == 8) {
+ if (InsecureRandBits(4) == 8) {
test.copy();
}
- if (((r >> 15) % 32) == 18) {
+ if (InsecureRandBits(5) == 18) {
test.move();
}
}
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index 8596734226..132e190051 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64());
BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
+ BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17));
+ BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7));
+ BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128));
BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
+ BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
+ BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50));
// Check that a nondeterministic ones are not
FastRandomContext ctx3;
FastRandomContext ctx4;
BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
+ BOOST_CHECK(ctx3.rand256() != ctx4.rand256());
+ BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
}
BOOST_AUTO_TEST_CASE(fastrandom_randbits)
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index e4ddf9d618..1de865776e 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -8,8 +8,6 @@
#include "test/test_bitcoin.h"
#include <boost/bind.hpp>
-#include <boost/random/mersenne_twister.hpp>
-#include <boost/random/uniform_int_distribution.hpp>
#include <boost/thread.hpp>
#include <boost/test/unit_test.hpp>
@@ -56,10 +54,10 @@ BOOST_AUTO_TEST_CASE(manythreads)
boost::mutex counterMutex[10];
int counter[10] = { 0 };
- boost::random::mt19937 rng(42);
- boost::random::uniform_int_distribution<> zeroToNine(0, 9);
- boost::random::uniform_int_distribution<> randomMsec(-11, 1000);
- boost::random::uniform_int_distribution<> randomDelta(-1000, 1000);
+ FastRandomContext rng(42);
+ auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
+ auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + rc.randrange(1012); }; // [-11, 1000]
+ auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + rc.randrange(2001); }; // [-1000, 1000]
boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
boost::chrono::system_clock::time_point now = start;
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 2f7c22084e..1ca83a7cf8 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -11,7 +11,6 @@
#include "serialize.h"
#include "streams.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include "util.h"
#include "utilstrencodings.h"
#include "version.h"
@@ -30,7 +29,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size())
{
- printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn);
return one;
}
CMutableTransaction txTmp(txTo);
@@ -61,7 +59,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
unsigned int nOut = nIn;
if (nOut >= txTmp.vout.size())
{
- printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut);
return one;
}
txTmp.vout.resize(nOut+1);
@@ -90,30 +87,30 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
void static RandomScript(CScript &script) {
static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
script = CScript();
- int ops = (insecure_rand() % 10);
+ int ops = (InsecureRandRange(10));
for (int i=0; i<ops; i++)
- script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
+ script << oplist[InsecureRandRange(sizeof(oplist)/sizeof(oplist[0]))];
}
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
- tx.nVersion = insecure_rand();
+ tx.nVersion = InsecureRand32();
tx.vin.clear();
tx.vout.clear();
- tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
- int ins = (insecure_rand() % 4) + 1;
- int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
+ tx.nLockTime = (InsecureRandBool()) ? InsecureRand32() : 0;
+ int ins = (InsecureRandBits(2)) + 1;
+ int outs = fSingle ? ins : (InsecureRandBits(2)) + 1;
for (int in = 0; in < ins; in++) {
tx.vin.push_back(CTxIn());
CTxIn &txin = tx.vin.back();
- txin.prevout.hash = GetRandHash();
- txin.prevout.n = insecure_rand() % 4;
+ txin.prevout.hash = InsecureRand256();
+ txin.prevout.n = InsecureRandBits(2);
RandomScript(txin.scriptSig);
- txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
+ txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1;
}
for (int out = 0; out < outs; out++) {
tx.vout.push_back(CTxOut());
CTxOut &txout = tx.vout.back();
- txout.nValue = insecure_rand() % 100000000;
+ txout.nValue = InsecureRandRange(100000000);
RandomScript(txout.scriptPubKey);
}
}
@@ -122,7 +119,7 @@ BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sighash_test)
{
- seed_insecure_rand(false);
+ SeedInsecureRand(false);
#if defined(PRINT_SIGHASH_JSON)
std::cout << "[\n";
@@ -134,12 +131,12 @@ BOOST_AUTO_TEST_CASE(sighash_test)
nRandomTests = 500;
#endif
for (int i=0; i<nRandomTests; i++) {
- int nHashType = insecure_rand();
+ int nHashType = InsecureRand32();
CMutableTransaction txTo;
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
CScript scriptCode;
RandomScript(scriptCode);
- int nIn = insecure_rand() % txTo.vin.size();
+ int nIn = InsecureRandRange(txTo.vin.size());
uint256 sh, sho;
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 0b2fe0ef9d..77c321cdf6 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -5,7 +5,6 @@
#include "chain.h"
#include "util.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <vector>
@@ -35,8 +34,8 @@ BOOST_AUTO_TEST_CASE(skiplist_test)
}
for (int i=0; i < 1000; i++) {
- int from = insecure_rand() % (SKIPLIST_LENGTH - 1);
- int to = insecure_rand() % (from + 1);
+ int from = InsecureRandRange(SKIPLIST_LENGTH - 1);
+ int to = InsecureRandRange(from + 1);
BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
@@ -78,7 +77,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
// Test 100 random starting points for locators.
for (int n=0; n<100; n++) {
- int r = insecure_rand() % 150000;
+ int r = InsecureRandRange(150000);
CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000];
CBlockLocator locator = chain.GetLocator(tip);
@@ -116,7 +115,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
} else {
// randomly choose something in the range [MTP, MTP*2]
int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast();
- int r = insecure_rand() % medianTimePast;
+ int r = InsecureRandRange(medianTimePast);
vBlocksMain[i].nTime = r + medianTimePast;
vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax);
}
@@ -135,7 +134,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
// Verify that FindEarliestAtLeast is correct.
for (unsigned int i=0; i<10000; ++i) {
// Pick a random element in vBlocksMain.
- int r = insecure_rand() % vBlocksMain.size();
+ int r = InsecureRandRange(vBlocksMain.size());
int64_t test_time = vBlocksMain[r].nTime;
CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
BOOST_CHECK(ret->nTimeMax >= test_time);
@@ -143,4 +142,39 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
}
}
+
+BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
+{
+ std::list<CBlockIndex> blocks;
+ for (unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) {
+ CBlockIndex* prev = blocks.empty() ? nullptr : &blocks.back();
+ blocks.emplace_back();
+ blocks.back().nHeight = prev ? prev->nHeight + 1 : 0;
+ blocks.back().pprev = prev;
+ blocks.back().BuildSkip();
+ blocks.back().nTimeMax = timeMax;
+ }
+
+ CChain chain;
+ chain.SetTip(&blocks.back());
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(350));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::min())->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index cb625bda11..c1aea1680a 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -59,7 +59,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
RegisterAllCoreRPCCommands(tableRPC);
ClearDatadirCache();
- pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
+ pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000)));
fs::create_directories(pathTemp);
ForceSetArg("-datadir", pathTemp.string());
mempool.setSanityCheck(1.0);
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index 60a86d8c48..0087eeb2d7 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -9,11 +9,32 @@
#include "fs.h"
#include "key.h"
#include "pubkey.h"
+#include "random.h"
#include "txdb.h"
#include "txmempool.h"
#include <boost/thread.hpp>
+extern uint256 insecure_rand_seed;
+extern FastRandomContext insecure_rand_ctx;
+
+static inline void SeedInsecureRand(bool fDeterministic = false)
+{
+ if (fDeterministic) {
+ insecure_rand_seed = uint256();
+ } else {
+ insecure_rand_seed = GetRandHash();
+ }
+ insecure_rand_ctx = FastRandomContext(insecure_rand_seed);
+}
+
+static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); }
+static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); }
+static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); }
+static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); }
+static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); }
+static inline std::vector<unsigned char> InsecureRandBytes(size_t len) { return insecure_rand_ctx.randbytes(len); }
+
/** Basic testing setup.
* This just configures logging and chain parameters.
*/
diff --git a/src/test/test_random.h b/src/test/test_random.h
deleted file mode 100644
index 318c44df4d..0000000000
--- a/src/test/test_random.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2016 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_TEST_RANDOM_H
-#define BITCOIN_TEST_RANDOM_H
-
-#include "random.h"
-
-extern uint256 insecure_rand_seed;
-extern FastRandomContext insecure_rand_ctx;
-
-static inline void seed_insecure_rand(bool fDeterministic = false)
-{
- if (fDeterministic) {
- insecure_rand_seed = uint256();
- } else {
- insecure_rand_seed = GetRandHash();
- }
- insecure_rand_ctx = FastRandomContext(insecure_rand_seed);
-}
-
-static inline uint32_t insecure_rand(void)
-{
- return insecure_rand_ctx.rand32();
-}
-
-#endif
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 10330c0c23..5e9dfb730b 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -10,7 +10,6 @@
#include "utilstrencodings.h"
#include "utilmoneystr.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include <stdint.h>
#include <vector>
@@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
{
- seed_insecure_rand(true);
+ SeedInsecureRand(true);
for (int mod=2;mod<11;mod++)
{
int mask = 1;
@@ -270,7 +269,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
for (int i = 0; i < 10000; i++) {
uint32_t rval;
do{
- rval=insecure_rand()&mask;
+ rval=InsecureRand32()&mask;
}while(rval>=(uint32_t)mod);
count += rval==0;
}
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 79405ec4d1..faa2383d14 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -5,7 +5,6 @@
#include "chain.h"
#include "versionbits.h"
#include "test/test_bitcoin.h"
-#include "test/test_random.h"
#include "chainparams.h"
#include "validation.h"
#include "consensus/params.h"
@@ -81,7 +80,7 @@ public:
VersionBitsTester& TestStateSinceHeight(int height) {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? NULL : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num));
}
}
@@ -91,7 +90,7 @@ public:
VersionBitsTester& TestDefined() {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num));
}
}
@@ -101,7 +100,7 @@ public:
VersionBitsTester& TestStarted() {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num));
}
}
@@ -111,7 +110,7 @@ public:
VersionBitsTester& TestLockedIn() {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
}
}
@@ -121,7 +120,7 @@ public:
VersionBitsTester& TestActive() {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num));
}
}
@@ -131,7 +130,7 @@ public:
VersionBitsTester& TestFailed() {
for (int i = 0; i < CHECKERS; i++) {
- if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ if (InsecureRandBits(i) == 0) {
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num));
}
}
diff --git a/src/validation.cpp b/src/validation.cpp
index de65839eef..eaefa95411 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -186,8 +186,11 @@ enum FlushStateMode {
};
// See definition for documentation
-bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0);
-void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
+static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0);
+static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
+static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
+static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = NULL);
+static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
bool CheckFinalTx(const CTransaction &tx, int flags)
{
@@ -309,7 +312,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
return EvaluateSequenceLocks(index, lockPair);
}
-void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
+static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
int expired = pool.Expire(GetTime() - age);
if (expired != 0) {
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
@@ -392,7 +395,7 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f
LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
}
-bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
+static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache)
{
@@ -410,7 +413,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
return state.DoS(100, false, REJECT_INVALID, "coinbase");
// Reject transactions with witness before segregated witness activates (override with -prematurewitness)
- bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus());
+ bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus());
if (!GetBoolArg("-prematurewitness",false) && tx.HasWitness() && !witnessEnabled) {
return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
}
@@ -739,7 +742,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
- if (!Params().RequireStandard()) {
+ if (!chainparams.RequireStandard()) {
scriptVerifyFlags = GetArg("-promiscuousmempoolflags", scriptVerifyFlags);
}
@@ -809,19 +812,20 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
return true;
}
-bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
+/** (try to) add transaction to memory pool with a specified acceptance time **/
+static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{
std::vector<COutPoint> coins_to_uncache;
- bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache);
+ bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache);
if (!res) {
BOOST_FOREACH(const COutPoint& hashTx, coins_to_uncache)
pcoinsTip->Uncache(hashTx);
}
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
CValidationState stateDummy;
- FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC);
+ FlushStateToDisk(chainparams, stateDummy, FLUSH_STATE_PERIODIC);
return res;
}
@@ -829,7 +833,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{
- return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee);
+ const CChainParams& chainparams = Params();
+ return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee);
}
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
@@ -898,7 +903,7 @@ bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus
// CBlock and CBlockIndex
//
-bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
+static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
{
// Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
@@ -1011,7 +1016,7 @@ static void AlertNotify(const std::string& strMessage)
boost::thread t(runCommand, strCmd); // thread runs free
}
-void CheckForkWarningConditions()
+static void CheckForkWarningConditions()
{
AssertLockHeld(cs_main);
// Before we get past initial download, we cannot reliably alert about forks
@@ -1052,7 +1057,7 @@ void CheckForkWarningConditions()
}
}
-void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
+static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
{
AssertLockHeld(cs_main);
// If we are on a fork that is sufficiently large, set a warning flag
@@ -1144,7 +1149,12 @@ int GetSpendHeight(const CCoinsViewCache& inputs)
return pindexPrev->nHeight + 1;
}
-bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks)
+/**
+ * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
+ * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
+ * instead of being performed inline.
+ */
+static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks)
{
if (!tx.IsCoinBase())
{
@@ -1411,7 +1421,7 @@ void static FlushBlockFile(bool fFinalize = false)
}
}
-bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
+static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
@@ -1730,9 +1740,8 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
* if they're too large, if it's been a while since the last write,
* or always and in all cases if we're in prune mode and are deleting files.
*/
-bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
+bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
- const CChainParams& chainparams = Params();
LOCK2(cs_main, cs_LastBlockFile);
static int64_t nLastWrite = 0;
static int64_t nLastFlush = 0;
@@ -1836,13 +1845,15 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int n
void FlushStateToDisk() {
CValidationState state;
- FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
+ const CChainParams& chainparams = Params();
+ FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS);
}
void PruneAndFlush() {
CValidationState state;
fCheckForPruning = true;
- FlushStateToDisk(state, FLUSH_STATE_NONE);
+ const CChainParams& chainparams = Params();
+ FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE);
}
static void DoWarning(const std::string& strWarning)
@@ -1939,7 +1950,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
}
LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Write the chain state to disk, if necessary.
- if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
+ if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
return false;
if (disconnectpool) {
@@ -2076,7 +2087,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint(BCLog::BENCH, " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
// Write the chain state to disk, if necessary.
- if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED))
+ if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED))
return false;
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint(BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
@@ -2336,7 +2347,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
CheckBlockIndex(chainparams.GetConsensus());
// Write changes periodically to disk, after relay.
- if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) {
+ if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_PERIODIC)) {
return false;
}
@@ -2453,7 +2464,7 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) {
return true;
}
-CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
+static CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
{
// Check for duplicate
uint256 hash = block.GetHash();
@@ -2537,7 +2548,7 @@ static bool ReceivedBlockTransactions(const CBlock &block, CValidationState& sta
return true;
}
-bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
+static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
{
LOCK(cs_LastBlockFile);
@@ -2594,7 +2605,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
return true;
}
-bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
+static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
{
pos.nFile = nFile;
@@ -2625,7 +2636,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true;
}
-bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW)
+static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
{
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
@@ -2775,7 +2786,10 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
return commitment;
}
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
+/** Context-dependent validity checks.
+ * By "context", we mean only the previous block headers, but not the UTXO
+ * set; UTXO-related validity checks are done in ConnectBlock(). */
+static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
{
assert(pindexPrev != NULL);
const int nHeight = pindexPrev->nHeight + 1;
@@ -2802,7 +2816,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return true;
}
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
+static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
@@ -3026,7 +3040,7 @@ static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidation
}
if (fCheckForPruning)
- FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
+ FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files
return true;
}
@@ -3094,7 +3108,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
*/
/* Calculate the amount of disk space the block & undo files currently use */
-uint64_t CalculateCurrentUsage()
+static uint64_t CalculateCurrentUsage()
{
uint64_t retval = 0;
BOOST_FOREACH(const CBlockFileInfo &file, vinfoBlockFile) {
@@ -3147,7 +3161,7 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
}
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
-void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight)
+static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight)
{
assert(fPruneMode && nManualPruneHeight > 0);
@@ -3172,11 +3186,26 @@ void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeig
void PruneBlockFilesManual(int nManualPruneHeight)
{
CValidationState state;
- FlushStateToDisk(state, FLUSH_STATE_NONE, nManualPruneHeight);
+ const CChainParams& chainparams = Params();
+ FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight);
}
-/* Calculate the block/rev files that should be deleted to remain under target*/
-void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
+/**
+ * Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target.
+ * The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new
+ * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex
+ * (which in this case means the blockchain must be re-downloaded.)
+ *
+ * Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set.
+ * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
+ * Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest).
+ * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
+ * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
+ * A db flag records the fact that at least some block files have been pruned.
+ *
+ * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned
+ */
+static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
{
LOCK2(cs_main, cs_LastBlockFile);
if (chainActive.Tip() == NULL || nPruneTarget == 0) {
@@ -3234,7 +3263,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes)
return true;
}
-FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
+static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
{
if (pos.IsNull())
return NULL;
@@ -3261,7 +3290,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) {
return OpenDiskFile(pos, "blk", fReadOnly);
}
-FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
+/** Open an undo file (rev?????.dat) */
+static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
return OpenDiskFile(pos, "rev", fReadOnly);
}
@@ -3533,7 +3563,7 @@ bool RewindBlockIndex(const CChainParams& params)
return error("RewindBlockIndex: unable to disconnect block at height %i", pindex->nHeight);
}
// Occasionally flush state to disk.
- if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC))
+ if (!FlushStateToDisk(params, state, FLUSH_STATE_PERIODIC))
return false;
}
@@ -3582,7 +3612,7 @@ bool RewindBlockIndex(const CChainParams& params)
CheckBlockIndex(params.GetConsensus());
- if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS)) {
+ if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) {
return false;
}
@@ -3655,7 +3685,7 @@ bool InitBlockIndex(const CChainParams& chainparams)
if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
return error("LoadBlockIndex(): genesis block not accepted");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
- return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
+ return FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS);
} catch (const std::runtime_error& e) {
return error("LoadBlockIndex(): failed to initialize block database: %s", e.what());
}
@@ -3997,6 +4027,7 @@ static const uint64_t MEMPOOL_DUMP_VERSION = 1;
bool LoadMempool(void)
{
+ const CChainParams& chainparams = Params();
int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb");
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
@@ -4033,7 +4064,7 @@ bool LoadMempool(void)
CValidationState state;
if (nTime + nExpiryTimeout > nNow) {
LOCK(cs_main);
- AcceptToMemoryPoolWithTime(mempool, state, tx, true, NULL, nTime);
+ AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, NULL, nTime, NULL, false, 0);
if (state.IsValid()) {
++count;
} else {
diff --git a/src/validation.h b/src/validation.h
index 096fd0a9ee..0f410530fb 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -30,8 +30,6 @@
#include <atomic>
-#include <boost/unordered_map.hpp>
-
class CBlockIndex;
class CBlockTreeDB;
class CBloomFilter;
@@ -161,7 +159,7 @@ extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
-typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
+typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
@@ -255,8 +253,6 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationS
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
-/** Open an undo file (rev?????.dat) */
-FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
/** Translation to a filesystem path */
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
/** Import blocks from an external file */
@@ -289,23 +285,6 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex);
/**
- * Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target.
- * The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new
- * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex
- * (which in this case means the blockchain must be re-downloaded.)
- *
- * Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set.
- * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.)
- * Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest).
- * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip.
- * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files.
- * A db flag records the fact that at least some block files have been pruned.
- *
- * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned
- */
-void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
-
-/**
* Mark one block file as pruned.
*/
void PruneOneBlockFile(const int fileNumber);
@@ -330,11 +309,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced = NULL,
bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
-/** (try to) add transaction to memory pool with a specified acceptance time **/
-bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,
- bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced = NULL,
- bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
-
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state);
@@ -348,14 +322,6 @@ BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::D
int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos);
-/**
- * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
- * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
- * instead of being performed inline.
- */
-bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
- unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = NULL);
-
/** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
@@ -428,22 +394,14 @@ public:
/** Functions for disk access for blocks */
-bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
/** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */
-bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-/** Context-dependent validity checks.
- * By "context", we mean only the previous block headers, but not the UTXO
- * set; UTXO-related validity checks are done in ConnectBlock(). */
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime);
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
-
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index 80786233f5..4bb352f23c 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -5,7 +5,7 @@
#include "versionbits.h"
#include "consensus/params.h"
-const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
+const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
{
/*.name =*/ "testdummy",
/*.gbt_force =*/ true,
diff --git a/src/versionbits.h b/src/versionbits.h
index f1d31ea0af..f4dfb71515 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -30,7 +30,7 @@ enum ThresholdState {
// will either be NULL or a block with (height + 1) % Period() == 0.
typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
-struct BIP9DeploymentInfo {
+struct VBDeploymentInfo {
/** Deployment name */
const char *name;
/** Whether GBT clients can safely ignore this rule in simplified usage */
@@ -45,7 +45,7 @@ struct BIP9Stats {
bool possible;
};
-extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[];
+extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[];
/**
* Abstract class that implements BIP9-style threshold logic, and caches results.
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 25f6bdd9d9..89f204bc31 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -211,7 +211,6 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco
{
CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
- std::string strType, strErr;
if (!(*recoverKVcallback)(callbackDataIn, ssKey, ssValue))
continue;
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 3b6dfd42ca..0841c23b86 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -21,6 +21,7 @@
#include "timedata.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "wallet/coincontrol.h"
#include "wallet/feebumper.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
@@ -2628,7 +2629,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"fundrawtransaction \"hexstring\" ( options )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
@@ -2657,6 +2658,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
" If no outputs are specified here, the sender pays the fee.\n"
" [vout_index,...]\n"
+ " \"optIntoRbf\" (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees\n"
" }\n"
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
@@ -2678,20 +2680,21 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR));
- CTxDestination changeAddress = CNoDestination();
+ CCoinControl coinControl;
+ coinControl.destChange = CNoDestination();
int changePosition = -1;
- bool includeWatching = false;
+ coinControl.fAllowWatchOnly = false; // include watching
bool lockUnspents = false;
bool reserveChangeKey = true;
- CFeeRate feeRate = CFeeRate(0);
- bool overrideEstimatedFeerate = false;
+ coinControl.nFeeRate = CFeeRate(0);
+ coinControl.fOverrideFeeRate = false;
UniValue subtractFeeFromOutputs;
std::set<int> setSubtractFeeFromOutputs;
if (request.params.size() > 1) {
if (request.params[1].type() == UniValue::VBOOL) {
// backward compatibility bool only fallback
- includeWatching = request.params[1].get_bool();
+ coinControl.fAllowWatchOnly = request.params[1].get_bool();
}
else {
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
@@ -2707,6 +2710,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
{"reserveChangeKey", UniValueType(UniValue::VBOOL)},
{"feeRate", UniValueType()}, // will be checked below
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
+ {"optIntoRbf", UniValueType(UniValue::VBOOL)},
},
true, true);
@@ -2716,14 +2720,14 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
- changeAddress = address.Get();
+ coinControl.destChange = address.Get();
}
if (options.exists("changePosition"))
changePosition = options["changePosition"].get_int();
if (options.exists("includeWatching"))
- includeWatching = options["includeWatching"].get_bool();
+ coinControl.fAllowWatchOnly = options["includeWatching"].get_bool();
if (options.exists("lockUnspents"))
lockUnspents = options["lockUnspents"].get_bool();
@@ -2733,12 +2737,16 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists("feeRate"))
{
- feeRate = CFeeRate(AmountFromValue(options["feeRate"]));
- overrideEstimatedFeerate = true;
+ coinControl.nFeeRate = CFeeRate(AmountFromValue(options["feeRate"]));
+ coinControl.fOverrideFeeRate = true;
}
if (options.exists("subtractFeeFromOutputs"))
subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
+
+ if (options.exists("optIntoRbf")) {
+ coinControl.signalRbf = options["optIntoRbf"].get_bool();
+ }
}
}
@@ -2767,7 +2775,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
CAmount nFeeOut;
std::string strFailReason;
- if (!pwallet->FundTransaction(tx, nFeeOut, overrideEstimatedFeerate, feeRate, changePosition, strFailReason, includeWatching, lockUnspents, setSubtractFeeFromOutputs, reserveChangeKey, changeAddress)) {
+ if (!pwallet->FundTransaction(tx, nFeeOut, changePosition, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl, reserveChangeKey)) {
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
}
diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp
index 0d012dacad..524a72c303 100644
--- a/src/wallet/test/crypto_tests.cpp
+++ b/src/wallet/test/crypto_tests.cpp
@@ -2,9 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "test/test_random.h"
-#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
+#include "utilstrencodings.h"
#include "wallet/crypter.h"
#include <vector>
@@ -193,7 +192,7 @@ BOOST_AUTO_TEST_CASE(passphrase) {
std::string hash(GetRandHash().ToString());
std::vector<unsigned char> vchSalt(8);
GetRandBytes(&vchSalt[0], vchSalt.size());
- uint32_t rounds = insecure_rand();
+ uint32_t rounds = InsecureRand32();
if (rounds > 30000)
rounds = 30000;
TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 3e000d2a9d..b2706d09f6 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2414,7 +2414,7 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
return true;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey, const CTxDestination& destChange)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl, bool keepReserveKey)
{
std::vector<CRecipient> vecSend;
@@ -2426,12 +2426,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
vecSend.push_back(recipient);
}
- CCoinControl coinControl;
- coinControl.destChange = destChange;
coinControl.fAllowOtherInputs = true;
- coinControl.fAllowWatchOnly = includeWatching;
- coinControl.fOverrideFeeRate = overrideEstimatedFeeRate;
- coinControl.nFeeRate = specificFeeRate;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
coinControl.Select(txin.prevout);
@@ -2690,9 +2685,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// and in the spirit of "smallest possible change from prior
// behavior."
bool rbf = coinControl ? coinControl->signalRbf : fWalletRbf;
+ const uint32_t nSequence = rbf ? MAX_BIP125_RBF_SEQUENCE : (std::numeric_limits<unsigned int>::max() - 1);
for (const auto& coin : setCoins)
txNew.vin.push_back(CTxIn(coin.outpoint,CScript(),
- std::numeric_limits<unsigned int>::max() - (rbf ? 2 : 1)));
+ nSequence));
// Fill in dummy signatures for fee calculation.
if (!DummySignTx(txNew, setCoins)) {
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a3974bf00b..a9c50aee4d 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -136,10 +136,7 @@ public:
std::string name;
std::string purpose;
- CAddressBookData()
- {
- purpose = "unknown";
- }
+ CAddressBookData() : purpose("unknown") {}
typedef std::map<std::string, std::string> StringMap;
StringMap destdata;
@@ -935,7 +932,7 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool overrideEstimatedFeeRate, const CFeeRate& specificFeeRate, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, bool keepReserveKey = true, const CTxDestination& destChange = CNoDestination());
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl, bool keepReserveKey = true);
bool SignTransaction(CMutableTransaction& tx);
/**
diff --git a/test/functional/config.ini.in b/test/config.ini.in
index 29586c555d..35ee092be4 100644
--- a/test/functional/config.ini.in
+++ b/test/config.ini.in
@@ -3,7 +3,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
# These environment variables are set by the build process and read by
-# test/functional/test_runner.py
+# test/functional/test_runner.py and test/util/bitcoin-util-test.py
[environment]
SRCDIR=@abs_top_srcdir@
diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py
index db66b7719c..87a50692f6 100755
--- a/test/functional/bip68-sequence.py
+++ b/test/functional/bip68-sequence.py
@@ -241,7 +241,7 @@ class BIP68Test(BitcoinTestFramework):
# Now mine some blocks, but make sure tx2 doesn't get mined.
# Use prioritisetransaction to lower the effective feerate to 0
- self.nodes[0].prioritisetransaction(tx2.hash, int(-self.relayfee*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(-self.relayfee*COIN))
cur_time = int(time.time())
for i in range(10):
self.nodes[0].setmocktime(cur_time + 600)
@@ -254,7 +254,7 @@ class BIP68Test(BitcoinTestFramework):
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
# Mine tx2, and then try again
- self.nodes[0].prioritisetransaction(tx2.hash, int(self.relayfee*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee*COIN))
# Advance the time on the node so that we can test timelocks
self.nodes[0].setmocktime(cur_time+600)
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py
index 5ada3e629e..6aef6d4489 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/blockchain.py
@@ -59,6 +59,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['transactions'], 200)
assert_equal(res['height'], 200)
assert_equal(res['txouts'], 200)
+ assert_equal(res['bogosize'], 17000),
assert_equal(res['bestblock'], node.getblockhash(200))
size = res['disk_size']
assert size > 6400
@@ -75,6 +76,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res2['total_amount'], Decimal('0'))
assert_equal(res2['height'], 0)
assert_equal(res2['txouts'], 0)
+ assert_equal(res2['bogosize'], 0),
assert_equal(res2['bestblock'], node.getblockhash(0))
assert_equal(len(res2['hash_serialized_2']), 64)
@@ -86,6 +88,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['transactions'], res3['transactions'])
assert_equal(res['height'], res3['height'])
assert_equal(res['txouts'], res3['txouts'])
+ assert_equal(res['bogosize'], res3['bogosize'])
assert_equal(res['bestblock'], res3['bestblock'])
assert_equal(res['hash_serialized_2'], res3['hash_serialized_2'])
diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py
index c41afe2b93..0a3166b89b 100755
--- a/test/functional/fundrawtransaction.py
+++ b/test/functional/fundrawtransaction.py
@@ -452,7 +452,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.stop_node(2)
self.stop_node(3)
self.nodes[1].encryptwallet("test")
- self.nodes.pop(1)
+ bitcoind_processes[1].wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT)
self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir)
# This test is not meant to test fee estimation and we'd like
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 72f04095f4..e225493816 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -96,7 +96,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
# Check that ancestor modified fees includes fee deltas from
# prioritisetransaction
- self.nodes[0].prioritisetransaction(chain[0], 1000)
+ self.nodes[0].prioritisetransaction(txid=chain[0], fee_delta=1000)
mempool = self.nodes[0].getrawmempool(True)
ancestor_fees = 0
for x in chain:
@@ -104,11 +104,11 @@ class MempoolPackagesTest(BitcoinTestFramework):
assert_equal(mempool[x]['ancestorfees'], ancestor_fees * COIN + 1000)
# Undo the prioritisetransaction for later tests
- self.nodes[0].prioritisetransaction(chain[0], -1000)
+ self.nodes[0].prioritisetransaction(txid=chain[0], fee_delta=-1000)
# Check that descendant modified fees includes fee deltas from
# prioritisetransaction
- self.nodes[0].prioritisetransaction(chain[-1], 1000)
+ self.nodes[0].prioritisetransaction(txid=chain[-1], fee_delta=1000)
mempool = self.nodes[0].getrawmempool(True)
descendant_fees = 0
@@ -126,7 +126,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
assert_equal(len(self.nodes[0].getrawmempool()), 0)
# Prioritise a transaction that has been mined, then add it back to the
# mempool by using invalidateblock.
- self.nodes[0].prioritisetransaction(chain[-1], 2000)
+ self.nodes[0].prioritisetransaction(txid=chain[-1], fee_delta=2000)
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
# Keep node1's tip synced with node0
self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py
index 9b302120ac..ff76e49fba 100755
--- a/test/functional/p2p-compactblocks.py
+++ b/test/functional/p2p-compactblocks.py
@@ -98,7 +98,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.setup_clean_chain = True
# Node0 = pre-segwit, node1 = segwit-aware
self.num_nodes = 2
- self.extra_args = [["-bip9params=segwit:0:0"], ["-txindex"]]
+ self.extra_args = [["-vbparams=segwit:0:0"], ["-txindex"]]
self.utxos = []
def build_block_on_tip(self, node, segwit=False):
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py
index ab97596ba3..dbc61d21fc 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p-segwit.py
@@ -114,7 +114,7 @@ class SegWitTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 3
- self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"]]
+ self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-vbparams=segwit:0:0"]]
def setup_network(self):
self.setup_nodes()
diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py
index 9c3b3fd5d9..4fc03d2547 100755
--- a/test/functional/prioritise_transaction.py
+++ b/test/functional/prioritise_transaction.py
@@ -46,7 +46,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
# add a fee delta to something in the cheapest bucket and make sure it gets mined
# also check that a different entry in the cheapest bucket is NOT mined
- self.nodes[0].prioritisetransaction(txids[0][0], int(3*base_fee*COIN))
+ self.nodes[0].prioritisetransaction(txid=txids[0][0], fee_delta=int(3*base_fee*COIN))
self.nodes[0].generate(1)
@@ -65,7 +65,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
# Add a prioritisation before a tx is in the mempool (de-prioritising a
# high-fee transaction so that it's now low fee).
- self.nodes[0].prioritisetransaction(high_fee_tx, -int(2*base_fee*COIN))
+ self.nodes[0].prioritisetransaction(txid=high_fee_tx, fee_delta=-int(2*base_fee*COIN))
# Add everything back to mempool
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
@@ -109,7 +109,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
# This is a less than 1000-byte transaction, so just set the fee
# to be the minimum for a 1000 byte transaction and check that it is
# accepted.
- self.nodes[0].prioritisetransaction(tx_id, int(self.relayfee*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=int(self.relayfee*COIN))
self.log.info("Assert that prioritised free transaction is accepted to mempool")
assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx_id)
@@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
mock_time = int(time.time())
self.nodes[0].setmocktime(mock_time)
template = self.nodes[0].getblocktemplate()
- self.nodes[0].prioritisetransaction(tx_id, -int(self.relayfee*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee*COIN))
self.nodes[0].setmocktime(mock_time+10)
new_template = self.nodes[0].getblocktemplate()
diff --git a/test/functional/replace-by-fee.py b/test/functional/replace-by-fee.py
index e940ce535c..ca7b623ca3 100755
--- a/test/functional/replace-by-fee.py
+++ b/test/functional/replace-by-fee.py
@@ -99,6 +99,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
self.log.info("Running test opt-in...")
self.test_opt_in()
+ self.log.info("Running test RPC...")
+ self.test_rpc()
+
self.log.info("Running test prioritised transactions...")
self.test_prioritised_transactions()
@@ -482,7 +485,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True)
# Use prioritisetransaction to set tx1a's fee to 0.
- self.nodes[0].prioritisetransaction(tx1a_txid, int(-0.1*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1*COIN))
# Now tx1b should be able to replace tx1a
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
@@ -509,12 +512,32 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True)
# Now prioritise tx2b to have a higher modified fee
- self.nodes[0].prioritisetransaction(tx2b.hash, int(0.1*COIN))
+ self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1*COIN))
# tx2b should now be accepted
tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
assert(tx2b_txid in self.nodes[0].getrawmempool())
+ def test_rpc(self):
+ us0 = self.nodes[0].listunspent()[0]
+ ins = [us0];
+ outs = {self.nodes[0].getnewaddress() : Decimal(1.0000000)}
+ rawtx0 = self.nodes[0].createrawtransaction(ins, outs, 0, True)
+ rawtx1 = self.nodes[0].createrawtransaction(ins, outs, 0, False)
+ json0 = self.nodes[0].decoderawtransaction(rawtx0)
+ json1 = self.nodes[0].decoderawtransaction(rawtx1)
+ assert_equal(json0["vin"][0]["sequence"], 4294967293)
+ assert_equal(json1["vin"][0]["sequence"], 4294967295)
+
+ rawtx2 = self.nodes[0].createrawtransaction([], outs)
+ frawtx2a = self.nodes[0].fundrawtransaction(rawtx2, {"optIntoRbf": True})
+ frawtx2b = self.nodes[0].fundrawtransaction(rawtx2, {"optIntoRbf": False})
+
+ json0 = self.nodes[0].decoderawtransaction(frawtx2a['hex'])
+ json1 = self.nodes[0].decoderawtransaction(frawtx2b['hex'])
+ assert_equal(json0["vin"][0]["sequence"], 4294967293)
+ assert_equal(json1["vin"][0]["sequence"], 4294967294)
+
if __name__ == '__main__':
ReplaceByFeeTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index b2aee7c739..4702f2d773 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -180,7 +180,7 @@ def main():
# Read config generated by configure.
config = configparser.ConfigParser()
- configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini"
+ configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini"
config.read_file(open(configfile))
passon_args.append("--configfile=%s" % configfile)
diff --git a/test/util/bctest.py b/test/util/bctest.py
deleted file mode 100644
index b17cf77ae3..0000000000
--- a/test/util/bctest.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright 2014 BitPay Inc.
-# Copyright 2016 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from __future__ import division,print_function,unicode_literals
-import subprocess
-import os
-import json
-import sys
-import binascii
-import difflib
-import logging
-import pprint
-
-def parse_output(a, fmt):
- """Parse the output according to specified format.
-
- Raise an error if the output can't be parsed."""
- if fmt == 'json': # json: compare parsed data
- return json.loads(a)
- elif fmt == 'hex': # hex: parse and compare binary data
- return binascii.a2b_hex(a.strip())
- else:
- raise NotImplementedError("Don't know how to compare %s" % fmt)
-
-def bctest(testDir, testObj, buildenv):
- """Runs a single test, comparing output and RC to expected output and RC.
-
- Raises an error if input can't be read, executable fails, or output/RC
- are not as expected. Error is caught by bctester() and reported.
- """
- # Get the exec names and arguments
- execprog = buildenv.BUILDDIR + "/src/" + testObj['exec'] + buildenv.exeext
- execargs = testObj['args']
- execrun = [execprog] + execargs
-
- # Read the input data (if there is any)
- stdinCfg = None
- inputData = None
- if "input" in testObj:
- filename = testDir + "/" + testObj['input']
- inputData = open(filename).read()
- stdinCfg = subprocess.PIPE
-
- # Read the expected output data (if there is any)
- outputFn = None
- outputData = None
- if "output_cmp" in testObj:
- outputFn = testObj['output_cmp']
- outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare)
- try:
- outputData = open(testDir + "/" + outputFn).read()
- except:
- logging.error("Output file " + outputFn + " can not be opened")
- raise
- if not outputData:
- logging.error("Output data missing for " + outputFn)
- raise Exception
-
- # Run the test
- proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True)
- try:
- outs = proc.communicate(input=inputData)
- except OSError:
- logging.error("OSError, Failed to execute " + execprog)
- raise
-
- if outputData:
- data_mismatch, formatting_mismatch = False, False
- # Parse command output and expected output
- try:
- a_parsed = parse_output(outs[0], outputType)
- except Exception as e:
- logging.error('Error parsing command output as %s: %s' % (outputType,e))
- raise
- try:
- b_parsed = parse_output(outputData, outputType)
- except Exception as e:
- logging.error('Error parsing expected output %s as %s: %s' % (outputFn,outputType,e))
- raise
- # Compare data
- if a_parsed != b_parsed:
- logging.error("Output data mismatch for " + outputFn + " (format " + outputType + ")")
- data_mismatch = True
- # Compare formatting
- if outs[0] != outputData:
- error_message = "Output formatting mismatch for " + outputFn + ":\n"
- error_message += "".join(difflib.context_diff(outputData.splitlines(True),
- outs[0].splitlines(True),
- fromfile=outputFn,
- tofile="returned"))
- logging.error(error_message)
- formatting_mismatch = True
-
- assert not data_mismatch and not formatting_mismatch
-
- # Compare the return code to the expected return code
- wantRC = 0
- if "return_code" in testObj:
- wantRC = testObj['return_code']
- if proc.returncode != wantRC:
- logging.error("Return code mismatch for " + outputFn)
- raise Exception
-
- if "error_txt" in testObj:
- want_error = testObj["error_txt"]
- # Compare error text
- # TODO: ideally, we'd compare the strings exactly and also assert
- # That stderr is empty if no errors are expected. However, bitcoin-tx
- # emits DISPLAY errors when running as a windows application on
- # linux through wine. Just assert that the expected error text appears
- # somewhere in stderr.
- if want_error not in outs[1]:
- logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip())
- raise Exception
-
-def bctester(testDir, input_basename, buildenv):
- """ Loads and parses the input file, runs all tests and reports results"""
- input_filename = testDir + "/" + input_basename
- raw_data = open(input_filename).read()
- input_data = json.loads(raw_data)
-
- failed_testcases = []
-
- for testObj in input_data:
- try:
- bctest(testDir, testObj, buildenv)
- logging.info("PASSED: " + testObj["description"])
- except:
- logging.info("FAILED: " + testObj["description"])
- failed_testcases.append(testObj["description"])
-
- if failed_testcases:
- error_message = "FAILED_TESTCASES:\n"
- error_message += pprint.pformat(failed_testcases, width=400)
- logging.error(error_message)
- sys.exit(1)
- else:
- sys.exit(0)
diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py
index e09a25159d..d15d6a6011 100755
--- a/test/util/bitcoin-util-test.py
+++ b/test/util/bitcoin-util-test.py
@@ -1,26 +1,30 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2014 BitPay Inc.
-# Copyright 2016 The Bitcoin Core developers
+# Copyright 2016-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.
-from __future__ import division,print_function,unicode_literals
-import os
-import sys
-import argparse
-import logging
+"""Test framework for bitcoin utils.
-help_text="""Test framework for bitcoin utils.
-
-Runs automatically during `make check`.
+Runs automatically during `make check`.
Can also be run manually."""
-if __name__ == '__main__':
- sys.path.append(os.path.dirname(os.path.abspath(__file__)))
- import buildenv
- import bctest
+import argparse
+import binascii
+import configparser
+import difflib
+import json
+import logging
+import os
+import pprint
+import subprocess
+import sys
- parser = argparse.ArgumentParser(description=help_text)
+def main():
+ config = configparser.ConfigParser()
+ config.read_file(open(os.path.dirname(__file__) + "/../config.ini"))
+
+ parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
verbose = args.verbose
@@ -31,6 +35,135 @@ if __name__ == '__main__':
level = logging.ERROR
formatter = '%(asctime)s - %(levelname)s - %(message)s'
# Add the format/level to the logger
- logging.basicConfig(format = formatter, level=level)
+ logging.basicConfig(format=formatter, level=level)
+
+ bctester(config["environment"]["SRCDIR"] + "/test/util/data", "bitcoin-util-test.json", config["environment"])
+
+def bctester(testDir, input_basename, buildenv):
+ """ Loads and parses the input file, runs all tests and reports results"""
+ input_filename = testDir + "/" + input_basename
+ raw_data = open(input_filename).read()
+ input_data = json.loads(raw_data)
+
+ failed_testcases = []
+
+ for testObj in input_data:
+ try:
+ bctest(testDir, testObj, buildenv)
+ logging.info("PASSED: " + testObj["description"])
+ except:
+ logging.info("FAILED: " + testObj["description"])
+ failed_testcases.append(testObj["description"])
- bctest.bctester(buildenv.SRCDIR + "/test/util/data", "bitcoin-util-test.json", buildenv)
+ if failed_testcases:
+ error_message = "FAILED_TESTCASES:\n"
+ error_message += pprint.pformat(failed_testcases, width=400)
+ logging.error(error_message)
+ sys.exit(1)
+ else:
+ sys.exit(0)
+
+def bctest(testDir, testObj, buildenv):
+ """Runs a single test, comparing output and RC to expected output and RC.
+
+ Raises an error if input can't be read, executable fails, or output/RC
+ are not as expected. Error is caught by bctester() and reported.
+ """
+ # Get the exec names and arguments
+ execprog = buildenv["BUILDDIR"] + "/src/" + testObj['exec'] + buildenv["EXEEXT"]
+ execargs = testObj['args']
+ execrun = [execprog] + execargs
+
+ # Read the input data (if there is any)
+ stdinCfg = None
+ inputData = None
+ if "input" in testObj:
+ filename = testDir + "/" + testObj['input']
+ inputData = open(filename).read()
+ stdinCfg = subprocess.PIPE
+
+ # Read the expected output data (if there is any)
+ outputFn = None
+ outputData = None
+ if "output_cmp" in testObj:
+ outputFn = testObj['output_cmp']
+ outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare)
+ try:
+ outputData = open(testDir + "/" + outputFn).read()
+ except:
+ logging.error("Output file " + outputFn + " can not be opened")
+ raise
+ if not outputData:
+ logging.error("Output data missing for " + outputFn)
+ raise Exception
+
+ # Run the test
+ proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+ try:
+ outs = proc.communicate(input=inputData)
+ except OSError:
+ logging.error("OSError, Failed to execute " + execprog)
+ raise
+
+ if outputData:
+ data_mismatch, formatting_mismatch = False, False
+ # Parse command output and expected output
+ try:
+ a_parsed = parse_output(outs[0], outputType)
+ except Exception as e:
+ logging.error('Error parsing command output as %s: %s' % (outputType, e))
+ raise
+ try:
+ b_parsed = parse_output(outputData, outputType)
+ except Exception as e:
+ logging.error('Error parsing expected output %s as %s: %s' % (outputFn, outputType, e))
+ raise
+ # Compare data
+ if a_parsed != b_parsed:
+ logging.error("Output data mismatch for " + outputFn + " (format " + outputType + ")")
+ data_mismatch = True
+ # Compare formatting
+ if outs[0] != outputData:
+ error_message = "Output formatting mismatch for " + outputFn + ":\n"
+ error_message += "".join(difflib.context_diff(outputData.splitlines(True),
+ outs[0].splitlines(True),
+ fromfile=outputFn,
+ tofile="returned"))
+ logging.error(error_message)
+ formatting_mismatch = True
+
+ assert not data_mismatch and not formatting_mismatch
+
+ # Compare the return code to the expected return code
+ wantRC = 0
+ if "return_code" in testObj:
+ wantRC = testObj['return_code']
+ if proc.returncode != wantRC:
+ logging.error("Return code mismatch for " + outputFn)
+ raise Exception
+
+ if "error_txt" in testObj:
+ want_error = testObj["error_txt"]
+ # Compare error text
+ # TODO: ideally, we'd compare the strings exactly and also assert
+ # That stderr is empty if no errors are expected. However, bitcoin-tx
+ # emits DISPLAY errors when running as a windows application on
+ # linux through wine. Just assert that the expected error text appears
+ # somewhere in stderr.
+ if want_error not in outs[1]:
+ logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip())
+ raise Exception
+
+def parse_output(a, fmt):
+ """Parse the output according to specified format.
+
+ Raise an error if the output can't be parsed."""
+ if fmt == 'json': # json: compare parsed data
+ return json.loads(a)
+ elif fmt == 'hex': # hex: parse and compare binary data
+ return binascii.a2b_hex(a.strip())
+ else:
+ raise NotImplementedError("Don't know how to compare %s" % fmt)
+
+if __name__ == '__main__':
+ main()
diff --git a/test/util/buildenv.py.in b/test/util/buildenv.py.in
deleted file mode 100644
index 33030b0348..0000000000
--- a/test/util/buildenv.py.in
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env python
-exeext="@EXEEXT@"
-SRCDIR="@abs_top_srcdir@"
-BUILDDIR="@abs_top_builddir@"