aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_msvc/README.md2
-rw-r--r--configure.ac13
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.test.include7
-rw-r--r--src/bench/ccoins_caching.cpp42
-rw-r--r--src/consensus/validation.h61
-rw-r--r--src/init.cpp3
-rw-r--r--src/miner.cpp3
-rw-r--r--src/net.cpp24
-rw-r--r--src/net.h15
-rw-r--r--src/net_processing.cpp7
-rw-r--r--src/node/transaction.cpp3
-rw-r--r--src/randomenv.cpp19
-rw-r--r--src/rpc/blockchain.cpp7
-rw-r--r--src/rpc/mining.cpp5
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp47
-rw-r--r--src/test/transaction_tests.cpp45
-rw-r--r--src/test/util/setup_common.cpp3
-rw-r--r--src/test/util/transaction_utils.cpp32
-rw-r--r--src/test/util/transaction_utils.h10
-rw-r--r--src/test/util_tests.cpp6
-rw-r--r--src/util/moneystr.cpp10
-rw-r--r--src/util/moneystr.h2
-rw-r--r--src/util/validation.cpp23
-rw-r--r--src/util/validation.h16
-rw-r--r--src/validation.cpp45
-rw-r--r--src/validationinterface.cpp3
-rw-r--r--src/wallet/feebumper.cpp1
-rw-r--r--src/wallet/test/coinselector_tests.cpp13
-rw-r--r--src/wallet/wallet.cpp1
-rwxr-xr-xtest/functional/feature_cltv.py2
-rwxr-xr-xtest/functional/feature_csv_activation.py79
-rwxr-xr-xtest/functional/feature_dersig.py5
-rwxr-xr-xtest/functional/feature_fee_estimation.py8
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py5
-rwxr-xr-xtest/functional/feature_nulldummy.py5
-rwxr-xr-xtest/functional/mempool_packages.py32
-rwxr-xr-xtest/functional/p2p_invalid_block.py2
-rwxr-xr-xtest/functional/p2p_segwit.py6
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py2
-rwxr-xr-xtest/functional/wallet_address_types.py2
-rwxr-xr-xtest/functional/wallet_avoidreuse.py2
-rwxr-xr-xtest/functional/wallet_backup.py8
-rwxr-xr-xtest/fuzz/test_runner.py1
44 files changed, 345 insertions, 284 deletions
diff --git a/build_msvc/README.md b/build_msvc/README.md
index e5aaf57abf..d4e710d55b 100644
--- a/build_msvc/README.md
+++ b/build_msvc/README.md
@@ -13,6 +13,7 @@ The minimal steps required to build Bitcoin Core with the msbuild toolchain are
```
vcpkg install --triplet x64-windows-static berkeleydb boost-filesystem boost-multi-index boost-signals2 boost-test boost-thread libevent[thread] rapidcheck zeromq double-conversion
+vcpkg integrate install
py -3 build_msvc\msvc-autogen.py
msbuild /m build_msvc\bitcoin.sln /p:Platform=x64 /p:Configuration=Release /t:build
```
@@ -56,6 +57,7 @@ The instructions below use `vcpkg` to install the dependencies.
```
PS >.\vcpkg install --triplet x64-windows-static $(Get-Content -Path build_msvc\vcpkg-packages.txt).split()
+PS >.\vcpkg integrate install
```
- Use Python to generate `*.vcxproj` from Makefile
diff --git a/configure.ac b/configure.ac
index d0fcf48713..35e5dc1fe7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -262,6 +262,13 @@ AC_ARG_ENABLE([gprof],
[enable_gprof=$enableval],
[enable_gprof=no])
+dnl Pass compiler & liner flags that make builds deterministic
+AC_ARG_ENABLE([determinism],
+ [AS_HELP_STRING([--enable-determinism],
+ [Enable compilation flags that make builds deterministic (default is no)])],
+ [enable_determinism=$enableval],
+ [enable_determinism=no])
+
dnl Turn warnings into errors
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
@@ -764,6 +771,12 @@ if test x$TARGET_OS = xdarwin; then
AX_CHECK_LINK_FLAG([[-Wl,-bind_at_load]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"])
fi
+if test x$enable_determinism = xyes; then
+ if test x$TARGET_OS = xwindows; then
+ AX_CHECK_LINK_FLAG([[-Wl,--no-insert-timestamp]], [LDFLAGS="$LDFLAGS -Wl,--no-insert-timestamp"])
+ fi
+fi
+
AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h sys/sysctl.h vm/vm_param.h sys/vmmeter.h sys/resources.h])
dnl FD_ZERO may be dependent on a declaration of memcpy, e.g. in SmartOS
diff --git a/src/Makefile.am b/src/Makefile.am
index eac7b38e03..0a1c45cf8c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -229,7 +229,6 @@ BITCOIN_CORE_H = \
util/time.h \
util/translation.h \
util/url.h \
- util/validation.h \
util/vector.h \
validation.h \
validationinterface.h \
@@ -528,7 +527,6 @@ libbitcoin_util_a_SOURCES = \
util/string.cpp \
util/time.cpp \
util/url.cpp \
- util/validation.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 7b4a6ae9f2..c474ae2442 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -39,6 +39,7 @@ FUZZ_TARGETS = \
test/fuzz/messageheader_deserialize \
test/fuzz/netaddr_deserialize \
test/fuzz/out_point_deserialize \
+ test/fuzz/p2p_transport_deserializer \
test/fuzz/parse_hd_keypath \
test/fuzz/parse_iso8601 \
test/fuzz/parse_numbers \
@@ -452,6 +453,12 @@ test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_out_point_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_out_point_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
+test_fuzz_p2p_transport_deserializer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_p2p_transport_deserializer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_p2p_transport_deserializer_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_p2p_transport_deserializer_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_p2p_transport_deserializer_SOURCES = $(FUZZ_SUITE) test/fuzz/p2p_transport_deserializer.cpp
+
test_fuzz_parse_hd_keypath_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_hd_keypath_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_hd_keypath_LDADD = $(FUZZ_SUITE_LD_COMMON)
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index c313029ea8..e9dd40293f 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -6,47 +6,10 @@
#include <coins.h>
#include <policy/policy.h>
#include <script/signingprovider.h>
+#include <test/util/transaction_utils.h>
#include <vector>
-// FIXME: Dedup with SetupDummyInputs in test/transaction_tests.cpp.
-//
-// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 COIN outputs
-// paid to a TX_PUBKEY, the second 21 and 22 COIN outputs
-// paid to a TX_PUBKEYHASH.
-//
-static std::vector<CMutableTransaction>
-SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet)
-{
- std::vector<CMutableTransaction> dummyTransactions;
- dummyTransactions.resize(2);
-
- // Add some keys to the keystore:
- CKey key[4];
- for (int i = 0; i < 4; i++) {
- key[i].MakeNewKey(i % 2);
- keystoreRet.AddKey(key[i]);
- }
-
- // Create some dummy input transactions
- dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11 * COIN;
- dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50 * COIN;
- dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
-
- dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21 * COIN;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
- dummyTransactions[1].vout[1].nValue = 22 * COIN;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
- AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
-
- return dummyTransactions;
-}
-
// Microbenchmark for simple accesses to a CCoinsViewCache database. Note from
// laanwj, "replicating the actual usage patterns of the client is hard though,
// many times micro-benchmarks of the database showed completely different
@@ -58,7 +21,8 @@ static void CCoinsCaching(benchmark::State& state)
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11 * COIN, 50 * COIN, 21 * COIN, 22 * COIN});
CMutableTransaction t1;
t1.vin.resize(3);
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 8a3abb31f4..a79e7b9d12 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -16,7 +16,7 @@
* provider of the transaction should be banned/ignored/disconnected/etc.
*/
enum class TxValidationResult {
- TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
+ TX_RESULT_UNSET = 0, //!< initial value. Tx has not yet been rejected
TX_CONSENSUS, //!< invalid by consensus rules
/**
* Invalid by a change to consensus rules more recent than SegWit.
@@ -50,7 +50,7 @@ enum class TxValidationResult {
* useful for some other use-cases.
*/
enum class BlockValidationResult {
- BLOCK_RESULT_UNSET, //!< initial value. Block has not yet been rejected
+ BLOCK_RESULT_UNSET = 0, //!< initial value. Block has not yet been rejected
BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
/**
* Invalid by a change to consensus rules more recent than SegWit.
@@ -71,31 +71,31 @@ enum class BlockValidationResult {
-/** Base class for capturing information about block/transaction validation. This is subclassed
+/** Template for capturing information about block/transaction validation. This is instantiated
* by TxValidationState and BlockValidationState for validation information on transactions
* and blocks respectively. */
+template <typename Result>
class ValidationState {
private:
enum mode_state {
MODE_VALID, //!< everything ok
MODE_INVALID, //!< network rule violation (DoS value may be set)
MODE_ERROR, //!< run-time error
- } m_mode;
+ } m_mode{MODE_VALID};
+ Result m_result{};
std::string m_reject_reason;
std::string m_debug_message;
-protected:
- void Invalid(const std::string &reject_reason="",
+public:
+ bool Invalid(Result result,
+ const std::string &reject_reason="",
const std::string &debug_message="")
{
+ m_result = result;
m_reject_reason = reject_reason;
m_debug_message = debug_message;
if (m_mode != MODE_ERROR) m_mode = MODE_INVALID;
+ return false;
}
-public:
- // ValidationState is abstract. Have a pure virtual destructor.
- virtual ~ValidationState() = 0;
-
- ValidationState() : m_mode(MODE_VALID) {}
bool Error(const std::string& reject_reason)
{
if (m_mode == MODE_VALID)
@@ -106,40 +106,25 @@ public:
bool IsValid() const { return m_mode == MODE_VALID; }
bool IsInvalid() const { return m_mode == MODE_INVALID; }
bool IsError() const { return m_mode == MODE_ERROR; }
+ Result GetResult() const { return m_result; }
std::string GetRejectReason() const { return m_reject_reason; }
std::string GetDebugMessage() const { return m_debug_message; }
-};
+ std::string ToString() const
+ {
+ if (IsValid()) {
+ return "Valid";
+ }
-inline ValidationState::~ValidationState() {};
+ if (!m_debug_message.empty()) {
+ return m_reject_reason + ", " + m_debug_message;
+ }
-class TxValidationState : public ValidationState {
-private:
- TxValidationResult m_result = TxValidationResult::TX_RESULT_UNSET;
-public:
- bool Invalid(TxValidationResult result,
- const std::string &reject_reason="",
- const std::string &debug_message="")
- {
- m_result = result;
- ValidationState::Invalid(reject_reason, debug_message);
- return false;
+ return m_reject_reason;
}
- TxValidationResult GetResult() const { return m_result; }
};
-class BlockValidationState : public ValidationState {
-private:
- BlockValidationResult m_result = BlockValidationResult::BLOCK_RESULT_UNSET;
-public:
- bool Invalid(BlockValidationResult result,
- const std::string &reject_reason="",
- const std::string &debug_message="") {
- m_result = result;
- ValidationState::Invalid(reject_reason, debug_message);
- return false;
- }
- BlockValidationResult GetResult() const { return m_result; }
-};
+class TxValidationState : public ValidationState<TxValidationResult> {};
+class BlockValidationState : public ValidationState<BlockValidationResult> {};
// These implement the weight = (stripped_size * 4) + witness_size formula,
// using only serialization with and without witness data. As witness_size
diff --git a/src/init.cpp b/src/init.cpp
index ece6214aa8..1c9faec803 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -51,7 +51,6 @@
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <util/asmap.h>
#include <validation.h>
#include <hash.h>
@@ -710,7 +709,7 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
// scan for better chains in the block chain database, that are not yet connected in the active best chain
BlockValidationState state;
if (!ActivateBestChain(state, chainparams)) {
- LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
+ LogPrintf("Failed to connect best block (%s)\n", state.ToString());
StartShutdown();
return;
}
diff --git a/src/miner.cpp b/src/miner.cpp
index 6f4e10b6ed..61d27d17c1 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -20,7 +20,6 @@
#include <timedata.h>
#include <util/moneystr.h>
#include <util/system.h>
-#include <util/validation.h>
#include <algorithm>
#include <utility>
@@ -167,7 +166,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
BlockValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
- throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
+ throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
}
int64_t nTime2 = GetTimeMicros();
diff --git a/src/net.cpp b/src/net.cpp
index 18fe95e675..cb4067e825 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -718,6 +718,19 @@ CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageSta
return msg;
}
+void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
+ // create dbl-sha256 checksum
+ uint256 hash = Hash(msg.data.begin(), msg.data.end());
+
+ // create header
+ CMessageHeader hdr(Params().MessageStart(), msg.command.c_str(), msg.data.size());
+ memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
+
+ // serialize header
+ header.reserve(CMessageHeader::HEADER_SIZE);
+ CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, header, 0, hdr};
+}
+
size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend)
{
auto it = pnode->vSendMsg.begin();
@@ -2705,6 +2718,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
}
m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
+ m_serializer = MakeUnique<V1TransportSerializer>(V1TransportSerializer());
}
CNode::~CNode()
@@ -2720,16 +2734,12 @@ bool CConnman::NodeFullyConnected(const CNode* pnode)
void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
{
size_t nMessageSize = msg.data.size();
- size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command), nMessageSize, pnode->GetId());
+ // make sure we use the appropriate network transport format
std::vector<unsigned char> serializedHeader;
- serializedHeader.reserve(CMessageHeader::HEADER_SIZE);
- uint256 hash = Hash(msg.data.data(), msg.data.data() + nMessageSize);
- CMessageHeader hdr(Params().MessageStart(), msg.command.c_str(), nMessageSize);
- memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
-
- CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, serializedHeader, 0, hdr};
+ pnode->m_serializer->prepareForTransport(msg, serializedHeader);
+ size_t nTotalSize = nMessageSize + serializedHeader.size();
size_t nBytesSent = 0;
{
diff --git a/src/net.h b/src/net.h
index 819947658a..7d3eaa2e0d 100644
--- a/src/net.h
+++ b/src/net.h
@@ -703,12 +703,27 @@ public:
CNetMessage GetMessage(const CMessageHeader::MessageStartChars& message_start, int64_t time) override;
};
+/** The TransportSerializer prepares messages for the network transport
+ */
+class TransportSerializer {
+public:
+ // prepare message for transport (header construction, error-correction computation, payload encryption, etc.)
+ virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) = 0;
+ virtual ~TransportSerializer() {}
+};
+
+class V1TransportSerializer : public TransportSerializer {
+public:
+ void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) override;
+};
+
/** Information about a peer */
class CNode
{
friend class CConnman;
public:
std::unique_ptr<TransportDeserializer> m_deserializer;
+ std::unique_ptr<TransportSerializer> m_serializer;
// socket
std::atomic<ServiceFlags> nServices{NODE_NONE};
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 1c1046b6ff..fa09b60630 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -26,7 +26,6 @@
#include <txmempool.h>
#include <util/system.h>
#include <util/strencodings.h>
-#include <util/validation.h>
#include <memory>
#include <typeinfo>
@@ -1432,7 +1431,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
if (need_activate_chain) {
BlockValidationState state;
if (!ActivateBestChain(state, Params(), a_recent_block)) {
- LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
+ LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
@@ -2342,7 +2341,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
BlockValidationState state;
if (!ActivateBestChain(state, Params(), a_recent_block)) {
- LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
+ LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
}
}
@@ -2636,7 +2635,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom->GetId(),
- FormatStateMessage(state));
+ state.ToString());
MaybePunishNodeForTx(pfrom->GetId(), state);
}
return true;
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 1bb9b88d00..201406ce3b 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -7,7 +7,6 @@
#include <net.h>
#include <net_processing.h>
#include <node/context.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <node/transaction.h>
@@ -41,7 +40,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
TxValidationState state;
if (!AcceptToMemoryPool(*node.mempool, state, std::move(tx),
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
- err_string = FormatStateMessage(state);
+ err_string = state.ToString();
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MISSING_INPUTS;
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index 6992c720ff..8b3d478529 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -38,11 +38,6 @@
#include <sys/utsname.h>
#include <unistd.h>
#endif
-#ifdef __MACH__
-#include <mach/clock.h>
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#endif
#if HAVE_DECL_GETIFADDRS
#include <ifaddrs.h>
#endif
@@ -237,8 +232,6 @@ void RandAddDynamicEnv(CSHA512& hasher)
GetSystemTimeAsFileTime(&ftime);
hasher << ftime;
#else
-# ifndef __MACH__
- // On non-MacOS systems, use various clock_gettime() calls.
struct timespec ts = {};
# ifdef CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -252,18 +245,6 @@ void RandAddDynamicEnv(CSHA512& hasher)
clock_gettime(CLOCK_BOOTTIME, &ts);
hasher << ts;
# endif
-# else
- // On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
- // and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME.
- hasher << mach_absolute_time();
- // From https://gist.github.com/jbenet/1087739
- clock_serv_t cclock;
- mach_timespec_t mts = {};
- if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) {
- hasher << mts;
- mach_port_deallocate(mach_task_self(), cclock);
- }
-# endif
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
struct timeval tv = {};
gettimeofday(&tv, nullptr);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 9b06aba22b..40637a552e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -31,7 +31,6 @@
#include <undo.h>
#include <util/strencodings.h>
#include <util/system.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -1486,7 +1485,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
PreciousBlock(state, Params(), pblockindex);
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
@@ -1524,7 +1523,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
}
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
@@ -1561,7 +1560,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
ActivateBestChain(state, Params());
if (!state.IsValid()) {
- throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
return NullUniValue;
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index ab5d830b2a..5bfdcd6555 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -28,7 +28,6 @@
#include <util/fees.h>
#include <util/strencodings.h>
#include <util/system.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
#include <versionbitsinfo.h>
@@ -307,7 +306,7 @@ static UniValue BIP22ValidationResult(const BlockValidationState& state)
return NullUniValue;
if (state.IsError())
- throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
if (state.IsInvalid())
{
std::string strRejectReason = state.GetRejectReason();
@@ -823,7 +822,7 @@ static UniValue submitheader(const JSONRPCRequest& request)
ProcessNewBlockHeaders({h}, state, Params());
if (state.IsValid()) return NullUniValue;
if (state.IsError()) {
- throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
}
throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
}
diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp
new file mode 100644
index 0000000000..57393fed45
--- /dev/null
+++ b/src/test/fuzz/p2p_transport_deserializer.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <net.h>
+#include <protocol.h>
+#include <test/fuzz/fuzz.h>
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <vector>
+
+void initialize()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ V1TransportDeserializer deserializer{Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION};
+ const char* pch = (const char*)buffer.data();
+ size_t n_bytes = buffer.size();
+ while (n_bytes > 0) {
+ const int handled = deserializer.Read(pch, n_bytes);
+ if (handled < 0) {
+ break;
+ }
+ pch += handled;
+ n_bytes -= handled;
+ if (deserializer.Complete()) {
+ const int64_t m_time = std::numeric_limits<int64_t>::max();
+ const CNetMessage msg = deserializer.GetMessage(Params().MessageStart(), m_time);
+ assert(msg.m_command.size() <= CMessageHeader::COMMAND_SIZE);
+ assert(msg.m_raw_message_size <= buffer.size());
+ assert(msg.m_raw_message_size == CMessageHeader::HEADER_SIZE + msg.m_message_size);
+ assert(msg.m_time == m_time);
+ if (msg.m_valid_header) {
+ assert(msg.m_valid_netmagic);
+ }
+ if (!msg.m_valid_netmagic) {
+ assert(!msg.m_valid_header);
+ }
+ }
+ }
+}
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index bcf4033fe4..44d4e0890a 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -22,6 +22,7 @@
#include <script/standard.h>
#include <streams.h>
#include <util/strencodings.h>
+#include <test/util/transaction_utils.h>
#include <map>
#include <string>
@@ -280,50 +281,13 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
BOOST_CHECK_MESSAGE(!CheckTransaction(CTransaction(tx), state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
-//
-// Helper: create two dummy transactions, each with
-// two outputs. The first has 11 and 50 CENT outputs
-// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
-// paid to a TX_PUBKEYHASH.
-//
-static std::vector<CMutableTransaction>
-SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet)
-{
- std::vector<CMutableTransaction> dummyTransactions;
- dummyTransactions.resize(2);
-
- // Add some keys to the keystore:
- CKey key[4];
- for (int i = 0; i < 4; i++)
- {
- key[i].MakeNewKey(i % 2);
- keystoreRet.AddKey(key[i]);
- }
-
- // Create some dummy input transactions
- dummyTransactions[0].vout.resize(2);
- dummyTransactions[0].vout[0].nValue = 11*CENT;
- dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
- dummyTransactions[0].vout[1].nValue = 50*CENT;
- dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
- AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
-
- dummyTransactions[1].vout.resize(2);
- dummyTransactions[1].vout[0].nValue = 21*CENT;
- dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
- dummyTransactions[1].vout[1].nValue = 22*CENT;
- dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
- AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
-
- return dummyTransactions;
-}
-
BOOST_AUTO_TEST_CASE(test_Get)
{
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
CMutableTransaction t1;
t1.vin.resize(3);
@@ -683,7 +647,8 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
- std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+ std::vector<CMutableTransaction> dummyTransactions =
+ SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});
CMutableTransaction t;
t.vin.resize(1);
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 360377e58a..fc736bc3a1 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -25,7 +25,6 @@
#include <util/strencodings.h>
#include <util/time.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
@@ -123,7 +122,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
BlockValidationState state;
if (!ActivateBestChain(state, chainparams)) {
- throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
+ throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
}
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
diff --git a/src/test/util/transaction_utils.cpp b/src/test/util/transaction_utils.cpp
index 90b78effb0..999b803a8d 100644
--- a/src/test/util/transaction_utils.cpp
+++ b/src/test/util/transaction_utils.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/util/transaction_utils.h>
+#include <coins.h>
+#include <script/signingprovider.h>
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue)
{
@@ -37,3 +39,33 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc
return txSpend;
}
+
+std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues)
+{
+ std::vector<CMutableTransaction> dummyTransactions;
+ dummyTransactions.resize(2);
+
+ // Add some keys to the keystore:
+ CKey key[4];
+ for (int i = 0; i < 4; i++) {
+ key[i].MakeNewKey(i % 2);
+ keystoreRet.AddKey(key[i]);
+ }
+
+ // Create some dummy input transactions
+ dummyTransactions[0].vout.resize(2);
+ dummyTransactions[0].vout[0].nValue = nValues[0];
+ dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
+ dummyTransactions[0].vout[1].nValue = nValues[1];
+ dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
+ AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
+
+ dummyTransactions[1].vout.resize(2);
+ dummyTransactions[1].vout[0].nValue = nValues[2];
+ dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey()));
+ dummyTransactions[1].vout[1].nValue = nValues[3];
+ dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey()));
+ AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
+
+ return dummyTransactions;
+}
diff --git a/src/test/util/transaction_utils.h b/src/test/util/transaction_utils.h
index 57604646e7..f843928a5f 100644
--- a/src/test/util/transaction_utils.h
+++ b/src/test/util/transaction_utils.h
@@ -7,6 +7,11 @@
#include <primitives/transaction.h>
+#include <array>
+
+class FillableSigningProvider;
+class CCoinsViewCache;
+
// create crediting transaction
// [1 coinbase input => 1 output with given scriptPubkey and value]
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0);
@@ -16,4 +21,9 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n
// 1 output with empty scriptPubKey, full value of referenced transaction]
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit);
+// Helper: create two dummy transactions, each with two outputs.
+// The first has nValues[0] and nValues[1] outputs paid to a TX_PUBKEY,
+// the second nValues[2] and nValues[3] outputs paid to a TX_PUBKEYHASH.
+std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues);
+
#endif // BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index f86e713676..536ff3ba25 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1199,6 +1199,12 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK(ParseMoney("0.00000001", ret));
BOOST_CHECK_EQUAL(ret, COIN/100000000);
+ // Parsing amount that can not be represented in ret should fail
+ BOOST_CHECK(!ParseMoney("0.000000001", ret));
+
+ // Parsing empty string should fail
+ BOOST_CHECK(!ParseMoney("", ret));
+
// Attempted 63 bit overflow should fail
BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index 2797f450ca..40d8918dfc 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -36,14 +36,14 @@ bool ParseMoney(const std::string& str, CAmount& nRet)
if (!ValidAsCString(str)) {
return false;
}
- return ParseMoney(str.c_str(), nRet);
-}
-bool ParseMoney(const char* pszIn, CAmount& nRet)
-{
+ if (str.empty()) {
+ return false;
+ }
+
std::string strWhole;
int64_t nUnits = 0;
- const char* p = pszIn;
+ const char* p = str.c_str();
while (IsSpace(*p))
p++;
for (; *p; p++)
diff --git a/src/util/moneystr.h b/src/util/moneystr.h
index 027c7e2e53..d8b08adc24 100644
--- a/src/util/moneystr.h
+++ b/src/util/moneystr.h
@@ -18,7 +18,7 @@
* JSON but use AmountFromValue and ValueFromAmount for that.
*/
std::string FormatMoney(const CAmount& n);
+/** Parse an amount denoted in full coins. E.g. "0.0034" supplied on the command line. **/
NODISCARD bool ParseMoney(const std::string& str, CAmount& nRet);
-NODISCARD bool ParseMoney(const char* pszIn, CAmount& nRet);
#endif // BITCOIN_UTIL_MONEYSTR_H
diff --git a/src/util/validation.cpp b/src/util/validation.cpp
deleted file mode 100644
index ffbee21aeb..0000000000
--- a/src/util/validation.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2020 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <util/validation.h>
-
-#include <consensus/validation.h>
-#include <tinyformat.h>
-
-std::string FormatStateMessage(const ValidationState &state)
-{
- if (state.IsValid()) {
- return "Valid";
- }
-
- const std::string debug_message = state.GetDebugMessage();
- if (!debug_message.empty()) {
- return strprintf("%s, %s", state.GetRejectReason(), debug_message);
- }
-
- return state.GetRejectReason();
-}
diff --git a/src/util/validation.h b/src/util/validation.h
deleted file mode 100644
index 5ee260a055..0000000000
--- a/src/util/validation.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_UTIL_VALIDATION_H
-#define BITCOIN_UTIL_VALIDATION_H
-
-#include <string>
-
-class ValidationState;
-
-/** Convert ValidationState to a human-readable message for logging */
-std::string FormatStateMessage(const ValidationState &state);
-
-#endif // BITCOIN_UTIL_VALIDATION_H
diff --git a/src/validation.cpp b/src/validation.cpp
index bab04b8e34..c0327c39bc 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -43,7 +43,6 @@
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -662,7 +661,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, m_view, GetSpendHeight(m_view), nFees)) {
- return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), state.ToString());
}
// Check for non-standard pay-to-script-hash in inputs
@@ -951,7 +950,7 @@ bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, Precomp
unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(::ChainActive().Tip(), chainparams.GetConsensus());
if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, txdata)) {
return error("%s: BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s",
- __func__, hash.ToString(), FormatStateMessage(state));
+ __func__, hash.ToString(), state.ToString());
}
return true;
@@ -1921,7 +1920,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// problems.
return AbortNode(state, "Corrupt block found indicating potential hardware failure; shutting down");
}
- return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString());
}
// verify that the view's current state corresponds to the previous block
@@ -2099,7 +2098,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
// Any transaction validation failure in ConnectBlock is a block consensus failure
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
- return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), state.ToString());
}
nFees += txfee;
if (!MoneyRange(nFees)) {
@@ -2142,7 +2141,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
return error("ConnectBlock(): CheckInputScripts on %s failed with %s",
- tx.GetHash().ToString(), FormatStateMessage(state));
+ tx.GetHash().ToString(), state.ToString());
}
control.Add(vChecks);
}
@@ -2359,7 +2358,7 @@ void CChainState::ForceFlushStateToDisk() {
BlockValidationState state;
const CChainParams& chainparams = Params();
if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -2369,7 +2368,7 @@ void CChainState::PruneAndFlush() {
const CChainParams& chainparams = Params();
if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -2596,7 +2595,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, const CChainParams& ch
if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
- return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), FormatStateMessage(state));
+ return error("%s: ConnectBlock %s failed, %s", __func__, pindexNew->GetBlockHash().ToString(), state.ToString());
}
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
@@ -3601,7 +3600,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
}
if (!CheckBlockHeader(block, state, chainparams.GetConsensus()))
- return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), state.ToString());
// Get prev block index
CBlockIndex* pindexPrev = nullptr;
@@ -3616,7 +3615,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
}
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
- return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), state.ToString());
/* Determine if this block descends from any block which has been found
* invalid (m_failed_blocks), then mark pindexPrev and any blocks between
@@ -3766,7 +3765,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
}
- return error("%s: %s", __func__, FormatStateMessage(state));
+ return error("%s: %s", __func__, state.ToString());
}
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
@@ -3816,7 +3815,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
}
if (!ret) {
GetMainSignals().BlockChecked(*pblock, state);
- return error("%s: AcceptBlock FAILED (%s)", __func__, FormatStateMessage(state));
+ return error("%s: AcceptBlock FAILED (%s)", __func__, state.ToString());
}
}
@@ -3824,7 +3823,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
BlockValidationState state; // Only used to report errors, not invalidity - ignore it
if (!::ChainstateActive().ActivateBestChain(state, chainparams, pblock))
- return error("%s: ActivateBestChain failed (%s)", __func__, FormatStateMessage(state));
+ return error("%s: ActivateBestChain failed (%s)", __func__, state.ToString());
return true;
}
@@ -3842,11 +3841,11 @@ bool TestBlockValidity(BlockValidationState& state, const CChainParams& chainpar
// NOTE: CheckBlockHeader is called by CheckBlock
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
- return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString());
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
- return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString());
if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev))
- return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
+ return error("%s: Consensus::ContextualCheckBlock: %s", __func__, state.ToString());
if (!::ChainstateActive().ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
return false;
assert(state.IsValid());
@@ -3944,7 +3943,7 @@ void PruneBlockFilesManual(int nManualPruneHeight)
const CChainParams& chainparams = Params();
if (!::ChainstateActive().FlushStateToDisk(
chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) {
- LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state));
+ LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@@ -4262,7 +4261,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus()))
return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
- pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
+ pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
CBlockUndo undo;
@@ -4311,7 +4310,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!::ChainstateActive().ConnectBlock(block, state, pindex, coins, chainparams))
- return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
+ return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
}
}
@@ -4499,7 +4498,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// Disconnect block
if (!DisconnectTip(state, params, nullptr)) {
- return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->nHeight, FormatStateMessage(state));
+ return error("RewindBlockIndex: unable to disconnect block at height %i (%s)", tip->nHeight, state.ToString());
}
// Reduce validity flag and have-data flags.
@@ -4519,7 +4518,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// Occasionally flush state to disk.
if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) {
- LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString());
return false;
}
}
@@ -4550,7 +4549,7 @@ bool RewindBlockIndex(const CChainParams& params) {
// it'll get called a bunch real soon.
BlockValidationState state;
if (!::ChainstateActive().FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) {
- LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state));
+ LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", state.ToString());
return false;
}
}
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 0f513c065f..1deb93c972 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -11,7 +11,6 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <scheduler.h>
-#include <util/validation.h>
#include <future>
#include <unordered_map>
@@ -193,7 +192,7 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
void CMainSignals::BlockChecked(const CBlock& block, const BlockValidationState& state) {
LOG_EVENT("%s: block hash=%s state=%s", __func__,
- block.GetHash().ToString(), FormatStateMessage(state));
+ block.GetHash().ToString(), state.ToString());
m_internals->BlockChecked(block, state);
}
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index b93b9ef1bc..486a6b8bf1 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -12,7 +12,6 @@
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/system.h>
-#include <util/validation.h>
//! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index d65a0e9075..21d57cb898 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -189,6 +189,19 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
actual_selection.clear();
selection.clear();
+ // Cost of change is greater than the difference between target value and utxo sum
+ add_coin(1 * CENT, 1, actual_selection);
+ BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
+ BOOST_CHECK_EQUAL(value_ret, 1 * CENT);
+ BOOST_CHECK(equal_sets(selection, actual_selection));
+ actual_selection.clear();
+ selection.clear();
+
+ // Cost of change is less than the difference between target value and utxo sum
+ BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0, selection, value_ret, not_input_fees));
+ actual_selection.clear();
+ selection.clear();
+
// Select 10 Cent
add_coin(5 * CENT, 5, utxo_pool);
add_coin(4 * CENT, 4, actual_selection);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 02fe59b601..5a97f62b71 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -27,7 +27,6 @@
#include <util/moneystr.h>
#include <util/rbf.h>
#include <util/translation.h>
-#include <util/validation.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 2c6f2e733b..e2b347f925 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -55,7 +55,7 @@ class BIP65Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [[
- '-whitelist=127.0.0.1',
+ '-whitelist=noban@127.0.0.1',
'-par=1', # Use only one script thread to get the exact reject reason for testing
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
]]
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index c2b4de54f2..a98480a6dd 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -35,6 +35,7 @@ bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evalu
bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
bip112tx_special - test negative argument to OP_CSV
+bip112tx_emptystack - test empty stack (= no argument) OP_CSV
"""
from decimal import Decimal
from itertools import product
@@ -56,6 +57,8 @@ from test_framework.util import (
softfork_active,
)
+TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
+COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
BASE_RELATIVE_LOCKTIME = 10
CSV_ACTIVATION_HEIGHT = 432
SEQ_DISABLE_FLAG = 1 << 31
@@ -95,6 +98,13 @@ def create_bip112special(node, input, txversion, address):
signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
return signtx
+def create_bip112emptystack(node, input, txversion, address):
+ tx = create_transaction(node, input, address, amount=Decimal("49.98"))
+ tx.nVersion = txversion
+ signtx = sign_transaction(node, tx)
+ signtx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(signtx.vin[0].scriptSig)))
+ return signtx
+
def send_generic_input_tx(node, coinbases, address):
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("49.99")))))
@@ -138,7 +148,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']]
+ self.extra_args = [[
+ '-whitelist=noban@127.0.0.1',
+ '-blockversion=4',
+ '-addresstype=legacy',
+ '-par=1', # Use only one script thread to get the exact reject reason for testing
+ ]]
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -163,11 +178,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
block.solve()
return block
- def send_blocks(self, blocks, success=True):
+ def send_blocks(self, blocks, success=True, reject_reason=None):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
Call with success = False if the tip shouldn't advance to the most recent block."""
- self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success)
+ self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason)
def run_test(self):
self.nodes[0].add_p2p_connection(P2PDataStore())
@@ -175,15 +190,16 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Generate blocks in the past for coinbase outputs.")
long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
- self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2 * 32 + 1) # 82 blocks generated for inputs
+ self.coinbase_blocks = self.nodes[0].generate(COINBASE_BLOCK_COUNT) # blocks generated for inputs
self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
- self.tipheight = 82 # height of the next block to build
+ self.tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
self.last_block_time = long_past_time
self.tip = int(self.nodes[0].getbestblockhash(), 16)
self.nodeaddress = self.nodes[0].getnewaddress()
# Activation height is hardcoded
- test_blocks = self.generate_blocks(345)
+ # We advance to block height five below BIP112 activation for the following tests
+ test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT-5 - COINBASE_BLOCK_COUNT)
self.send_blocks(test_blocks)
assert not softfork_active(self.nodes[0], 'csv')
@@ -214,6 +230,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
bip112specialinput = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
+ # 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
+ bip112emptystackinput = send_generic_input_tx(self.nodes[0],self.coinbase_blocks, self.nodeaddress)
# 1 normal input
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
@@ -224,7 +242,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.tip = int(inputblockhash, 16)
self.tipheight += 1
self.last_block_time += 600
- assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), 82 + 1)
+ assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), TESTING_TX_COUNT + 1)
# 2 more version 4 blocks
test_blocks = self.generate_blocks(2)
@@ -263,6 +281,9 @@ class BIP68_112_113Test(BitcoinTestFramework):
# -1 OP_CSV OP_DROP input
bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress)
bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress)
+ # (empty stack) OP_CSV input
+ bip112tx_emptystack_v1 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 1, self.nodeaddress)
+ bip112tx_emptystack_v2 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 2, self.nodeaddress)
self.log.info("TESTING")
@@ -270,11 +291,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Test version 1 txs")
success_txs = []
- # add BIP113 tx and -1 CSV tx
+ # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
success_txs.append(bip113signed1)
success_txs.append(bip112tx_special_v1)
+ success_txs.append(bip112tx_emptystack_v1)
# add BIP 68 txs
success_txs.extend(all_rlt_txs(bip68txs_v1))
# add BIP 112 with seq=10 txs
@@ -289,11 +311,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("Test version 2 txs")
success_txs = []
- # add BIP113 tx and -1 CSV tx
+ # BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
success_txs.append(bip113signed2)
success_txs.append(bip112tx_special_v2)
+ success_txs.append(bip112tx_emptystack_v2)
# add BIP 68 txs
success_txs.extend(all_rlt_txs(bip68txs_v2))
# add BIP 112 with seq=10 txs
@@ -320,7 +343,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
for bip113tx in [bip113signed1, bip113signed2]:
- self.send_blocks([self.create_test_block([bip113tx])], success=False)
+ self.send_blocks([self.create_test_block([bip113tx])], success=False, reject_reason='bad-txns-nonfinal')
# BIP 113 tests should now pass if the locktime is < MTP
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
@@ -352,11 +375,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
# All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
bip68timetxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and tx['stf']]
for tx in bip68timetxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
bip68heighttxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and not tx['stf']]
for tx in bip68heighttxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
# Advance one block to 438
test_blocks = self.generate_blocks(1)
@@ -367,7 +390,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block(bip68success_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
for tx in bip68heighttxs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False, reject_reason='bad-txns-nonfinal')
# Advance one block to 439
test_blocks = self.generate_blocks(1)
@@ -381,8 +404,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.log.info("BIP 112 tests")
self.log.info("Test version 1 txs")
- # -1 OP_CSV tx should fail
- self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False)
+ # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
+ self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Negative locktime)')
+ self.send_blocks([self.create_test_block([bip112tx_emptystack_v1])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
@@ -393,15 +419,19 @@ class BIP68_112_113Test(BitcoinTestFramework):
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
fail_txs = all_rlt_txs(bip112txs_vary_nSequence_v1)
fail_txs += all_rlt_txs(bip112txs_vary_nSequence_9_v1)
- fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
+ fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if not tx['sdf']]
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
self.log.info("Test version 2 txs")
- # -1 OP_CSV tx should fail
- self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False)
+ # -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
+ self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Negative locktime)')
+ self.send_blocks([self.create_test_block([bip112tx_emptystack_v2])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
@@ -416,18 +446,21 @@ class BIP68_112_113Test(BitcoinTestFramework):
fail_txs = all_rlt_txs(bip112txs_vary_nSequence_9_v2)
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if tx['sdf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# If sequencelock types mismatch, tx should fail
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and tx['stf']]
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]
for tx in fail_txs:
- self.send_blocks([self.create_test_block([tx])], success=False)
+ self.send_blocks([self.create_test_block([tx])], success=False,
+ reject_reason='non-mandatory-script-verify-flag (Locktime requirement not satisfied)')
# Remaining txs should pass, just test masking works properly
success_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and not tx['stf']]
@@ -445,7 +478,5 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.send_blocks([self.create_test_block(time_txs)])
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
- # TODO: Test empty stack fails
-
if __name__ == '__main__':
BIP68_112_113Test().main()
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index 27da49cf24..9628945a80 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -40,7 +40,10 @@ def unDERify(tx):
class BIP66Test(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact log msg for testing
+ self.extra_args = [[
+ '-whitelist=noban@127.0.0.1',
+ '-par=1', # Use only one script thread to get the exact log msg for testing
+ ]]
self.setup_clean_chain = True
self.rpc_timeout = 120
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index d2d41b1206..1b33724594 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -128,11 +128,11 @@ class EstimateFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 3
# mine non-standard txs (e.g. txs with "dust" outputs)
- # Force fSendTrickle to true (via whitelist)
+ # Force fSendTrickle to true (via whitelist.noban)
self.extra_args = [
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1"],
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1", "-blockmaxweight=68000"],
- ["-acceptnonstdtxn", "-whitelist=127.0.0.1", "-blockmaxweight=32000"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1", "-blockmaxweight=68000"],
+ ["-acceptnonstdtxn", "-whitelist=noban@127.0.0.1", "-blockmaxweight=32000"],
]
def skip_test_if_missing_module(self):
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 8d200915bd..974388d798 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -140,10 +140,9 @@ class MaxUploadTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
- #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1
- self.log.info("Restarting nodes with -whitelist=127.0.0.1")
+ self.log.info("Restarting node 0 with noban permission and 1MB maxuploadtarget")
self.stop_node(0)
- self.start_node(0, ["-whitelist=127.0.0.1", "-maxuploadtarget=1"])
+ self.start_node(0, ["-whitelist=noban@127.0.0.1", "-maxuploadtarget=1"])
# Reconnect to self.nodes[0]
self.nodes[0].add_p2p_connection(TestP2PConn())
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index aaf56a42d0..9c92ee7f90 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -41,7 +41,10 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
# normal segwit activation here (and don't use the default always-on behaviour).
- self.extra_args = [['-whitelist=127.0.0.1', '-segwitheight=432', '-addresstype=legacy']]
+ self.extra_args = [[
+ '-segwitheight=432',
+ '-addresstype=legacy',
+ ]]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 7014105d88..a07dad18d6 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -12,6 +12,7 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
satoshi_round,
+ wait_until,
)
# default limits
@@ -19,13 +20,22 @@ MAX_ANCESTORS = 25
MAX_DESCENDANTS = 25
# custom limits for node1
MAX_ANCESTORS_CUSTOM = 5
+MAX_DESCENDANTS_CUSTOM = 10
+assert MAX_DESCENDANTS_CUSTOM >= MAX_ANCESTORS_CUSTOM
class MempoolPackagesTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [
- ["-maxorphantx=1000"],
- ["-maxorphantx=1000", "-limitancestorcount={}".format(MAX_ANCESTORS_CUSTOM)],
+ [
+ "-maxorphantx=1000",
+ "-whitelist=noban@127.0.0.1", # immediate tx relay
+ ],
+ [
+ "-maxorphantx=1000",
+ "-limitancestorcount={}".format(MAX_ANCESTORS_CUSTOM),
+ "-limitdescendantcount={}".format(MAX_DESCENDANTS_CUSTOM),
+ ],
]
def skip_test_if_missing_module(self):
@@ -219,9 +229,11 @@ class MempoolPackagesTest(BitcoinTestFramework):
transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value})
# Sign and send up to MAX_DESCENDANT transactions chained off the parent tx
+ chain = [] # save sent txs for the purpose of checking node1's mempool later (see below)
for i in range(MAX_DESCENDANTS - 1):
utxo = transaction_package.pop(0)
(txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
+ chain.append(txid)
if utxo['txid'] is parent_transaction:
tx_children.append(txid)
for j in range(10):
@@ -238,7 +250,21 @@ class MempoolPackagesTest(BitcoinTestFramework):
utxo = transaction_package.pop(0)
assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
- # TODO: check that node1's mempool is as expected
+ # Check that node1's mempool is as expected, containing:
+ # - txs from previous ancestor test (-> custom ancestor limit)
+ # - parent tx for descendant test
+ # - txs chained off parent tx (-> custom descendant limit)
+ wait_until(lambda: len(self.nodes[1].getrawmempool(False)) ==
+ MAX_ANCESTORS_CUSTOM + 1 + MAX_DESCENDANTS_CUSTOM, timeout=10)
+ mempool0 = self.nodes[0].getrawmempool(False)
+ mempool1 = self.nodes[1].getrawmempool(False)
+ assert set(mempool1).issubset(set(mempool0))
+ assert parent_transaction in mempool1
+ for tx in chain[:MAX_DESCENDANTS_CUSTOM]:
+ assert tx in mempool1
+ for tx in chain[MAX_DESCENDANTS_CUSTOM:]:
+ assert tx not in mempool1
+ # TODO: more detailed check of node1's mempool (fees etc.)
# TODO: test descendant size limits
diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py
index 905534b862..801407757f 100755
--- a/test/functional/p2p_invalid_block.py
+++ b/test/functional/p2p_invalid_block.py
@@ -22,7 +22,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [["-whitelist=127.0.0.1"]]
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]]
def run_test(self):
# Add p2p connection to node0
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 3223c27e0b..ad5a124680 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -188,9 +188,9 @@ class SegWitTest(BitcoinTestFramework):
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
self.extra_args = [
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT)],
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
- ["-whitelist=127.0.0.1", "-acceptnonstdtxn=1", "-segwitheight=-1"]
+ ["-acceptnonstdtxn=1", "-segwitheight={}".format(SEGWIT_HEIGHT), "-whitelist=noban@127.0.0.1"],
+ ["-acceptnonstdtxn=0", "-segwitheight={}".format(SEGWIT_HEIGHT)],
+ ["-acceptnonstdtxn=1", "-segwitheight=-1"],
]
self.supports_cli = False
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 6f1ae0d3ba..c435ef24ce 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -30,7 +30,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This test isn't testing tx relay. Set whitelist on the peers for
# instant tx relay.
- self.extra_args = [['-whitelist=127.0.0.1']] * self.num_nodes
+ self.extra_args = [['-whitelist=noban@127.0.0.1']] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index f08606e622..79b6db986b 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -82,7 +82,7 @@ class AddressTypeTest(BitcoinTestFramework):
]
# whitelist all peers to speed up tx relay / mempool sync
for args in self.extra_args:
- args.append("-whitelist=127.0.0.1")
+ args.append("-whitelist=noban@127.0.0.1")
self.supports_cli = False
def skip_test_if_missing_module(self):
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index 1ca02a695c..8e2dc03ac2 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -70,7 +70,7 @@ class AvoidReuseTest(BitcoinTestFramework):
self.num_nodes = 2
# This test isn't testing txn relay/timing, so set whitelist on the
# peers for instant txn relay. This speeds up the test run time 2-3x.
- self.extra_args = [["-whitelist=127.0.0.1"]] * self.num_nodes
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 16c69f304a..fb80a06433 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -50,10 +50,10 @@ class WalletBackupTest(BitcoinTestFramework):
# nodes 1, 2,3 are spenders, let's give them a keypool=100
# whitelist all peers to speed up tx relay / mempool sync
self.extra_args = [
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-keypool=100", "-whitelist=127.0.0.1"],
- ["-whitelist=127.0.0.1"]
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1", "-keypool=100"],
+ ["-whitelist=noban@127.0.0.1"],
]
self.rpc_timeout = 120
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index dafb5d9806..1a74c67503 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -30,6 +30,7 @@ FUZZERS_MISSING_CORPORA = [
"key_origin_info_deserialize",
"merkle_block_deserialize",
"out_point_deserialize",
+ "p2p_transport_deserializer",
"parse_hd_keypath",
"parse_numbers",
"parse_script",