mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge pull request #5548 from kwvg/fuzz6
backport: merge bitcoin#19143, #20377, #20946, #20936, #21226, #21264, #19259, #21380, #21489, #19288, #19055, #20882, #21185, #21115, partial bitcoin#11389 (fuzzing harness backports: part 6)
This commit is contained in:
commit
2b32dd6394
@ -14,4 +14,4 @@ export DEP_OPTS="NO_UPNP=1 DEBUG=1"
|
||||
export RUN_UNIT_TESTS_SEQUENTIAL="true"
|
||||
export RUN_UNIT_TESTS="false"
|
||||
export GOAL="install"
|
||||
export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
export BITCOIN_CONFIG="--enable-zmq --enable-reduce-exports --disable-fuzz-binary LDFLAGS=-static-libstdc++"
|
||||
|
20
configure.ac
20
configure.ac
@ -178,10 +178,16 @@ AC_ARG_ENABLE([extended-functional-tests],
|
||||
|
||||
AC_ARG_ENABLE([fuzz],
|
||||
AS_HELP_STRING([--enable-fuzz],
|
||||
[enable building of fuzz targets (default no). enabling this will disable all other targets]),
|
||||
[build for fuzzing (default no). enabling this will disable all other targets and override --{enable,disable}-fuzz-binary]),
|
||||
[enable_fuzz=$enableval],
|
||||
[enable_fuzz=no])
|
||||
|
||||
AC_ARG_ENABLE([fuzz-binary],
|
||||
AS_HELP_STRING([--enable-fuzz-binary],
|
||||
[enable building of fuzz binary (default yes).]),
|
||||
[enable_fuzz_binary=$enableval],
|
||||
[enable_fuzz_binary=yes])
|
||||
|
||||
AC_ARG_ENABLE([danger_fuzz_link_all],
|
||||
AS_HELP_STRING([--enable-danger-fuzz-link-all],
|
||||
[Danger! Modifies source code. Needs git and gnu sed installed. Link each fuzz target (default no).]),
|
||||
@ -1275,7 +1281,7 @@ AC_DEFUN([SUPPRESS_WARNINGS],
|
||||
|
||||
dnl enable-fuzz should disable all other targets
|
||||
if test "x$enable_fuzz" = "xyes"; then
|
||||
AC_MSG_WARN(enable-fuzz will disable all other targets)
|
||||
AC_MSG_WARN(enable-fuzz will disable all other targets and force --enable-fuzz-binary=yes)
|
||||
build_bitcoin_utils=no
|
||||
build_bitcoin_cli=no
|
||||
build_bitcoin_tx=no
|
||||
@ -1290,15 +1296,16 @@ if test "x$enable_fuzz" = "xyes"; then
|
||||
use_upnp=no
|
||||
use_natpmp=no
|
||||
use_zmq=no
|
||||
enable_fuzz_binary=yes
|
||||
|
||||
AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
|
||||
|
||||
AC_MSG_CHECKING([whether main function is needed])
|
||||
AC_MSG_CHECKING([whether main function is needed for fuzz binary])
|
||||
AX_CHECK_LINK_FLAG(
|
||||
[[-fsanitize=$use_sanitizers]],
|
||||
[AC_MSG_RESULT([no])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
CPPFLAGS="$CPPFLAGS -DPROVIDE_MAIN_FUNCTION"],
|
||||
CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION"],
|
||||
[],
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <cstdint>
|
||||
@ -1321,6 +1328,8 @@ else
|
||||
QT_DBUS_INCLUDES=SUPPRESS_WARNINGS($QT_DBUS_INCLUDES)
|
||||
QT_TEST_INCLUDES=SUPPRESS_WARNINGS($QT_TEST_INCLUDES)
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -DPROVIDE_FUZZ_MAIN_FUNCTION"
|
||||
fi
|
||||
|
||||
if test x$enable_wallet != xno; then
|
||||
@ -1733,6 +1742,7 @@ AM_CONDITIONAL([USE_SQLITE], [test "x$use_sqlite" = "xyes"])
|
||||
AM_CONDITIONAL([USE_BDB], [test "x$use_bdb" = "xyes"])
|
||||
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
|
||||
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
|
||||
AM_CONDITIONAL([ENABLE_FUZZ_BINARY],[test x$enable_fuzz_binary = xyes])
|
||||
AM_CONDITIONAL([ENABLE_FUZZ_LINK_ALL],[test x$enable_danger_fuzz_link_all = xyes])
|
||||
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
|
||||
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
|
||||
@ -1748,6 +1758,8 @@ AM_CONDITIONAL([ENABLE_ARM_CRC],[test x$enable_arm_crc = xyes])
|
||||
AM_CONDITIONAL([ENABLE_ARM_SHANI], [test "$enable_arm_shani" = "yes"])
|
||||
AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes])
|
||||
AM_CONDITIONAL([WORDS_BIGENDIAN],[test x$ac_cv_c_bigendian = xyes])
|
||||
AM_CONDITIONAL([USE_NATPMP],[test x$use_natpmp = xyes])
|
||||
AM_CONDITIONAL([USE_UPNP],[test x$use_upnp = xyes])
|
||||
|
||||
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
|
||||
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
|
||||
|
@ -508,6 +508,7 @@ libbitcoin_wallet_a_SOURCES = \
|
||||
coinjoin/client.cpp \
|
||||
coinjoin/options.cpp \
|
||||
coinjoin/util.cpp \
|
||||
hdchain.cpp \
|
||||
wallet/coincontrol.cpp \
|
||||
wallet/context.cpp \
|
||||
wallet/crypter.cpp \
|
||||
@ -682,7 +683,6 @@ libbitcoin_common_a_SOURCES = \
|
||||
compressor.cpp \
|
||||
core_read.cpp \
|
||||
core_write.cpp \
|
||||
hdchain.cpp \
|
||||
key.cpp \
|
||||
key_io.cpp \
|
||||
merkleblock.cpp \
|
||||
|
@ -3,9 +3,11 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
if ENABLE_FUZZ
|
||||
if ENABLE_FUZZ_BINARY
|
||||
noinst_PROGRAMS += test/fuzz/fuzz
|
||||
else
|
||||
endif
|
||||
|
||||
if !ENABLE_FUZZ
|
||||
bin_PROGRAMS += test/test_dash
|
||||
endif
|
||||
|
||||
@ -61,6 +63,14 @@ FUZZ_SUITE_LD_COMMON = \
|
||||
$(GMP_LIBS) \
|
||||
$(BACKTRACE_LIB)
|
||||
|
||||
if USE_UPNP
|
||||
FUZZ_SUITE_LD_COMMON += $(MINIUPNPC_LIBS)
|
||||
endif
|
||||
|
||||
if USE_NATPMP
|
||||
FUZZ_SUITE_LD_COMMON += $(NATPMP_LIBS)
|
||||
endif
|
||||
|
||||
# test_dash binary #
|
||||
BITCOIN_TESTS =\
|
||||
test/arith_uint256_tests.cpp \
|
||||
@ -178,10 +188,16 @@ BITCOIN_TESTS += \
|
||||
wallet/test/ismine_tests.cpp \
|
||||
wallet/test/scriptpubkeyman_tests.cpp
|
||||
|
||||
FUZZ_SUITE_LD_COMMON +=\
|
||||
$(LIBBITCOIN_WALLET) \
|
||||
$(SQLITE_LIBS) \
|
||||
$(BDB_LIBS)
|
||||
|
||||
if USE_BDB
|
||||
BITCOIN_TESTS += wallet/test/db_tests.cpp
|
||||
endif
|
||||
|
||||
|
||||
BITCOIN_TEST_SUITE += \
|
||||
wallet/test/wallet_test_fixture.cpp \
|
||||
wallet/test/wallet_test_fixture.h \
|
||||
@ -204,11 +220,12 @@ test_test_dash_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $
|
||||
|
||||
if ENABLE_ZMQ
|
||||
test_test_dash_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
||||
FUZZ_SUITE_LD_COMMON += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
||||
endif
|
||||
|
||||
if ENABLE_FUZZ
|
||||
FUZZ_SUITE_LDFLAGS_COMMON = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(LDFLAGS_WRAP_EXCEPTIONS) $(PTHREAD_FLAGS)
|
||||
|
||||
if ENABLE_FUZZ_BINARY
|
||||
test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_fuzz_fuzz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_fuzz_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||
@ -240,6 +257,7 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
|
||||
test/fuzz/crypto_poly1305.cpp \
|
||||
test/fuzz/cuckoocache.cpp \
|
||||
test/fuzz/data_stream.cpp \
|
||||
test/fuzz/decode_tx.cpp \
|
||||
test/fuzz/descriptor_parse.cpp \
|
||||
test/fuzz/deserialize.cpp \
|
||||
@ -260,6 +278,7 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/locale.cpp \
|
||||
test/fuzz/merkleblock.cpp \
|
||||
test/fuzz/message.cpp \
|
||||
test/fuzz/muhash.cpp \
|
||||
test/fuzz/multiplication_overflow.cpp \
|
||||
test/fuzz/net.cpp \
|
||||
test/fuzz/net_permissions.cpp \
|
||||
@ -272,6 +291,7 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/parse_script.cpp \
|
||||
test/fuzz/parse_univalue.cpp \
|
||||
test/fuzz/policy_estimator.cpp \
|
||||
test/fuzz/policy_estimator_io.cpp \
|
||||
test/fuzz/pow.cpp \
|
||||
test/fuzz/prevector.cpp \
|
||||
test/fuzz/primitives_transaction.cpp \
|
||||
@ -300,11 +320,13 @@ test_fuzz_fuzz_SOURCES = \
|
||||
test/fuzz/strprintf.cpp \
|
||||
test/fuzz/system.cpp \
|
||||
test/fuzz/timedata.cpp \
|
||||
test/fuzz/torcontrol.cpp \
|
||||
test/fuzz/transaction.cpp \
|
||||
test/fuzz/tx_in.cpp \
|
||||
test/fuzz/tx_out.cpp
|
||||
|
||||
endif # ENABLE_FUZZ
|
||||
test/fuzz/tx_out.cpp \
|
||||
test/fuzz/validation_load_mempool.cpp \
|
||||
test/fuzz/versionbits.cpp
|
||||
endif # ENABLE_FUZZ_BINARY
|
||||
|
||||
nodist_test_test_dash_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
||||
|
@ -136,6 +136,7 @@ public:
|
||||
CMainParams() {
|
||||
strNetworkID = CBaseChainParams::MAIN;
|
||||
consensus.nSubsidyHalvingInterval = 210240; // Note: actual number of blocks per calendar year with DGW v3 is ~200700 (for example 449750 - 249050)
|
||||
consensus.BIP16Height = 0;
|
||||
consensus.nMasternodePaymentsStartBlock = 100000; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock
|
||||
consensus.nMasternodePaymentsIncreaseBlock = 158000; // actual historical value
|
||||
consensus.nMasternodePaymentsIncreasePeriod = 576*30; // 17280 - actual historical value
|
||||
@ -182,7 +183,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 19999999999; // TODO: To be determined later
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 4032;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 3226; // 80% of 4032
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 2420; // 60% of 4032
|
||||
@ -190,7 +191,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 4032;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 3226; // 80% of 4032
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 2420; // 60% of 4032
|
||||
@ -332,6 +333,7 @@ public:
|
||||
CTestNetParams() {
|
||||
strNetworkID = CBaseChainParams::TESTNET;
|
||||
consensus.nSubsidyHalvingInterval = 210240;
|
||||
consensus.BIP16Height = 0;
|
||||
consensus.nMasternodePaymentsStartBlock = 4010; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock
|
||||
consensus.nMasternodePaymentsIncreaseBlock = 4030;
|
||||
consensus.nMasternodePaymentsIncreasePeriod = 10;
|
||||
@ -378,7 +380,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 19999999999; // TODO: To be determined later
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 100;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 80; // 80% of 100
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 60; // 60% of 100
|
||||
@ -386,7 +388,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 100;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100
|
||||
@ -503,6 +505,7 @@ public:
|
||||
explicit CDevNetParams(const ArgsManager& args) {
|
||||
strNetworkID = CBaseChainParams::DEVNET;
|
||||
consensus.nSubsidyHalvingInterval = 210240;
|
||||
consensus.BIP16Height = 0;
|
||||
consensus.nMasternodePaymentsStartBlock = 4010; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock
|
||||
consensus.nMasternodePaymentsIncreaseBlock = 4030;
|
||||
consensus.nMasternodePaymentsIncreasePeriod = 10;
|
||||
@ -548,7 +551,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 1661990400; // Sep 1st, 2022
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 120;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 80; // 80% of 100
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 60; // 60% of 100
|
||||
@ -556,7 +559,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 1661990400; // Sep 1st, 2022
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 120;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100
|
||||
@ -739,6 +742,7 @@ public:
|
||||
explicit CRegTestParams(const ArgsManager& args) {
|
||||
strNetworkID = CBaseChainParams::REGTEST;
|
||||
consensus.nSubsidyHalvingInterval = 150;
|
||||
consensus.BIP16Height = 0; // always enforce P2SH BIP16 on regtest
|
||||
consensus.nMasternodePaymentsStartBlock = 240;
|
||||
consensus.nMasternodePaymentsIncreaseBlock = 350;
|
||||
consensus.nMasternodePaymentsIncreasePeriod = 10;
|
||||
@ -781,11 +785,11 @@ public:
|
||||
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 480;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 384; // 80% of 480
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 288; // 60% of 480
|
||||
@ -793,7 +797,7 @@ public:
|
||||
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 0;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 1030;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 800; // 80% of 1000
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 600; // 60% of 1000
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <uint256.h>
|
||||
#include <llmq/params.h>
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
||||
namespace Consensus {
|
||||
@ -39,6 +40,15 @@ struct BIP9Deployment {
|
||||
int64_t nThresholdMin{0};
|
||||
/** A coefficient which adjusts the speed a required number of signaling blocks is decreasing from nThresholdStart to nThresholdMin at with each period. */
|
||||
int64_t nFalloffCoeff{0};
|
||||
|
||||
/** Constant for nTimeout very far in the future. */
|
||||
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
|
||||
|
||||
/** Special value for nStartTime indicating that the deployment is always active.
|
||||
* This is useful for testing, as it means tests don't need to deal with the activation
|
||||
* process (which takes at least 3 BIP9 intervals). Only tests that specifically test the
|
||||
* behaviour during activation cannot use this. */
|
||||
static constexpr int64_t ALWAYS_ACTIVE = -1;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -48,6 +58,8 @@ struct Params {
|
||||
uint256 hashGenesisBlock;
|
||||
uint256 hashDevnetGenesisBlock;
|
||||
int nSubsidyHalvingInterval;
|
||||
/** Block height at which BIP16 becomes active */
|
||||
int BIP16Height;
|
||||
int nMasternodePaymentsStartBlock;
|
||||
int nMasternodePaymentsIncreaseBlock;
|
||||
int nMasternodePaymentsIncreasePeriod; // in blocks
|
||||
|
@ -26,7 +26,7 @@ int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
|
||||
void initialize_banman()
|
||||
{
|
||||
InitializeFuzzingContext();
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(banman, initialize_banman)
|
||||
|
@ -37,9 +37,7 @@ bool operator==(const Coin& a, const Coin& b)
|
||||
|
||||
void initialize_coins_view()
|
||||
{
|
||||
static const ECCVerifyHandle ecc_verify_handle;
|
||||
ECC_Start();
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
void initialize_connman()
|
||||
{
|
||||
InitializeFuzzingContext();
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(connman, initialize_connman)
|
||||
|
25
src/test/fuzz/data_stream.cpp
Normal file
25
src/test/fuzz/data_stream.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 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 <addrman.h>
|
||||
#include <net.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
void initialize_data_stream_addr_man()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(data_stream_addr_man, initialize_data_stream_addr_man)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
|
||||
CAddrMan addr_man;
|
||||
CAddrDB::Read(addr_man, data_stream);
|
||||
}
|
@ -43,7 +43,7 @@ void initialize()
|
||||
std::get<1>(it->second)();
|
||||
}
|
||||
|
||||
#if defined(PROVIDE_MAIN_FUNCTION)
|
||||
#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)
|
||||
static bool read_stdin(std::vector<uint8_t>& data)
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
@ -71,8 +71,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(PROVIDE_MAIN_FUNCTION)
|
||||
__attribute__((weak)) int main(int argc, char** argv)
|
||||
#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
initialize();
|
||||
static const auto& test_one_input = *Assert(g_test_one_input);
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
void initialize_i2p()
|
||||
{
|
||||
InitializeFuzzingContext();
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(i2p, initialize_i2p)
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <merkleblock.h>
|
||||
#include <policy/fees.h>
|
||||
#include <rpc/util.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
@ -9,9 +11,31 @@
|
||||
#include <util/error.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr TransactionError ALL_TRANSACTION_ERROR[] = {
|
||||
TransactionError::OK,
|
||||
TransactionError::MISSING_INPUTS,
|
||||
TransactionError::ALREADY_IN_CHAIN,
|
||||
TransactionError::P2P_DISABLED,
|
||||
TransactionError::MEMPOOL_REJECTED,
|
||||
TransactionError::MEMPOOL_ERROR,
|
||||
TransactionError::INVALID_PSBT,
|
||||
TransactionError::PSBT_MISMATCH,
|
||||
TransactionError::SIGHASH_MISMATCH,
|
||||
TransactionError::MAX_FEE_EXCEEDED,
|
||||
};
|
||||
|
||||
constexpr FeeEstimateHorizon ALL_FEE_EST_HORIZON[] = {
|
||||
FeeEstimateHorizon::SHORT_HALFLIFE,
|
||||
FeeEstimateHorizon::MED_HALFLIFE,
|
||||
FeeEstimateHorizon::LONG_HALFLIFE,
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
// The fuzzing kitchen sink: Fuzzing harness for functions that need to be
|
||||
// fuzzed but a.) don't belong in any existing fuzzing harness file, and
|
||||
// b.) are not important enough to warrant their own fuzzing harness file.
|
||||
@ -19,8 +43,15 @@ FUZZ_TARGET(kitchen_sink)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
|
||||
const TransactionError transaction_error = fuzzed_data_provider.PickValueInArray<TransactionError>({TransactionError::OK, TransactionError::MISSING_INPUTS, TransactionError::ALREADY_IN_CHAIN, TransactionError::P2P_DISABLED, TransactionError::MEMPOOL_REJECTED, TransactionError::MEMPOOL_ERROR, TransactionError::INVALID_PSBT, TransactionError::PSBT_MISMATCH, TransactionError::SIGHASH_MISMATCH, TransactionError::MAX_FEE_EXCEEDED});
|
||||
const TransactionError transaction_error = fuzzed_data_provider.PickValueInArray(ALL_TRANSACTION_ERROR);
|
||||
(void)JSONRPCTransactionError(transaction_error);
|
||||
(void)RPCErrorFromTransactionError(transaction_error);
|
||||
(void)TransactionErrorString(transaction_error);
|
||||
|
||||
(void)StringForFeeEstimateHorizon(fuzzed_data_provider.PickValueInArray(ALL_FEE_EST_HORIZON));
|
||||
|
||||
const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
const std::vector<bool> bits = BytesToBits(bytes);
|
||||
const std::vector<uint8_t> bytes_decoded = BitsToBytes(bits);
|
||||
assert(bytes == bytes_decoded);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
void initialize_load_external_block_file()
|
||||
{
|
||||
InitializeFuzzingContext();
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
|
||||
|
63
src/test/fuzz/muhash.cpp
Normal file
63
src/test/fuzz/muhash.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (c) 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 <crypto/muhash.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
FUZZ_TARGET(muhash)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
std::vector<uint8_t> data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
std::vector<uint8_t> data2 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
if (data.empty()) {
|
||||
data.resize(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 4096), fuzzed_data_provider.ConsumeIntegral<uint8_t>());
|
||||
}
|
||||
if (data2.empty()) {
|
||||
data2.resize(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 4096), fuzzed_data_provider.ConsumeIntegral<uint8_t>());
|
||||
}
|
||||
|
||||
data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
data2 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
|
||||
|
||||
MuHash3072 muhash;
|
||||
|
||||
// Test that MuHash result is consistent independent of order of operations
|
||||
muhash.Insert(data);
|
||||
muhash.Insert(data2);
|
||||
|
||||
uint256 out;
|
||||
muhash.Finalize(out);
|
||||
|
||||
muhash = MuHash3072();
|
||||
muhash.Insert(data2);
|
||||
muhash.Insert(data);
|
||||
|
||||
uint256 out2;
|
||||
muhash.Finalize(out2);
|
||||
|
||||
assert(out == out2);
|
||||
MuHash3072 muhash3;
|
||||
muhash3 *= muhash;
|
||||
uint256 out3;
|
||||
muhash3.Finalize(out3);
|
||||
assert(out == out3);
|
||||
|
||||
// Test that removing all added elements brings the object back to it's initial state
|
||||
muhash /= muhash;
|
||||
muhash.Finalize(out);
|
||||
|
||||
MuHash3072 muhash2;
|
||||
muhash2.Finalize(out2);
|
||||
|
||||
assert(out == out2);
|
||||
|
||||
muhash3.Remove(data);
|
||||
muhash3.Remove(data2);
|
||||
muhash3.Finalize(out3);
|
||||
assert(out == out3);
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
|
||||
void initialize_net()
|
||||
{
|
||||
static const BasicTestingSetup basic_testing_setup;
|
||||
static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::MAIN);
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(net, initialize_net)
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <netinet/in.h>
|
||||
#include <vector>
|
||||
|
||||
FUZZ_TARGET(netaddress)
|
||||
|
@ -14,7 +14,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
FUZZ_TARGET(policy_estimator)
|
||||
void initialize_policy_estimator()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
CBlockPolicyEstimator block_policy_estimator;
|
||||
@ -62,4 +67,10 @@ FUZZ_TARGET(policy_estimator)
|
||||
(void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
|
||||
(void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
|
||||
}
|
||||
{
|
||||
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||
CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
|
||||
block_policy_estimator.Write(fuzzed_auto_file);
|
||||
block_policy_estimator.Read(fuzzed_auto_file);
|
||||
}
|
||||
}
|
||||
|
28
src/test/fuzz/policy_estimator_io.cpp
Normal file
28
src/test/fuzz/policy_estimator_io.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 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 <policy/fees.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
void initialize_policy_estimator_io()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
|
||||
CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
|
||||
// Re-using block_policy_estimator across runs to avoid costly creation of CBlockPolicyEstimator object.
|
||||
static CBlockPolicyEstimator block_policy_estimator;
|
||||
if (block_policy_estimator.Read(fuzzed_auto_file)) {
|
||||
block_policy_estimator.Write(fuzzed_auto_file);
|
||||
}
|
||||
}
|
@ -44,14 +44,8 @@ const TestingSetup* g_setup;
|
||||
|
||||
void initialize_process_message()
|
||||
{
|
||||
static TestingSetup setup{
|
||||
CBaseChainParams::REGTEST,
|
||||
{
|
||||
"-nodebuglogfile",
|
||||
},
|
||||
};
|
||||
g_setup = &setup;
|
||||
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
g_setup = testing_setup.get();
|
||||
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
|
||||
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
|
||||
}
|
||||
|
@ -15,18 +15,14 @@
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
|
||||
namespace {
|
||||
const TestingSetup* g_setup;
|
||||
} // namespace
|
||||
|
||||
void initialize_process_messages()
|
||||
{
|
||||
static TestingSetup setup{
|
||||
CBaseChainParams::REGTEST,
|
||||
{
|
||||
"-nodebuglogfile",
|
||||
},
|
||||
};
|
||||
g_setup = &setup;
|
||||
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
g_setup = testing_setup.get();
|
||||
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
|
||||
MineBlock(g_setup->m_node, CScript() << OP_TRUE);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ extern int g_socks5_recv_timeout;
|
||||
|
||||
void initialize_socks5()
|
||||
{
|
||||
InitializeFuzzingContext();
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
default_socks5_recv_timeout = g_socks5_recv_timeout;
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,9 @@ FUZZ_TARGET(string)
|
||||
}
|
||||
(void)SanitizeString(random_string_1);
|
||||
(void)SanitizeString(random_string_1, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3));
|
||||
#ifndef WIN32
|
||||
(void)ShellEscape(random_string_1);
|
||||
#endif // WIN32
|
||||
uint16_t port_out;
|
||||
std::string host_out;
|
||||
SplitHostPort(random_string_1, port_out, host_out);
|
||||
|
79
src/test/fuzz/torcontrol.cpp
Normal file
79
src/test/fuzz/torcontrol.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 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 <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <torcontrol.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class DummyTorControlConnection : public TorControlConnection
|
||||
{
|
||||
public:
|
||||
DummyTorControlConnection() : TorControlConnection{nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
bool Connect(const std::string&, const ConnectionCB&, const ConnectionCB&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disconnect()
|
||||
{
|
||||
}
|
||||
|
||||
bool Command(const std::string&, const ReplyHandlerCB&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void initialize_torcontrol()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(torcontrol, initialize_torcontrol)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
|
||||
TorController tor_controller;
|
||||
while (fuzzed_data_provider.ConsumeBool()) {
|
||||
TorControlReply tor_control_reply;
|
||||
CallOneOf(
|
||||
fuzzed_data_provider,
|
||||
[&] {
|
||||
tor_control_reply.code = 250;
|
||||
},
|
||||
[&] {
|
||||
tor_control_reply.code = 510;
|
||||
},
|
||||
[&] {
|
||||
tor_control_reply.code = fuzzed_data_provider.ConsumeIntegral<int>();
|
||||
});
|
||||
tor_control_reply.lines = ConsumeRandomLengthStringVector(fuzzed_data_provider);
|
||||
if (tor_control_reply.lines.empty()) {
|
||||
break;
|
||||
}
|
||||
DummyTorControlConnection dummy_tor_control_connection;
|
||||
CallOneOf(
|
||||
fuzzed_data_provider,
|
||||
[&] {
|
||||
tor_controller.add_onion_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
},
|
||||
[&] {
|
||||
tor_controller.auth_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
},
|
||||
[&] {
|
||||
tor_controller.authchallenge_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
},
|
||||
[&] {
|
||||
tor_controller.protocolinfo_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
});
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@
|
||||
#include <txmempool.h>
|
||||
#include <uint256.h>
|
||||
#include <util/time.h>
|
||||
#include <util/vector.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -247,6 +248,16 @@ void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider, const std::array<T
|
||||
errno = fuzzed_data_provider.PickValueInArray(errnos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a fuzzed errno in the range [0, 133 (EHWPOISON)]. Can be used from functions emulating
|
||||
* standard library functions that set errno, or in other contexts where the value of errno
|
||||
* might be relevant for the execution path that will be taken.
|
||||
*/
|
||||
inline void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider) noexcept
|
||||
{
|
||||
errno = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 133);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte vector of specified size regardless of the number of remaining bytes available
|
||||
* from the fuzzer. Pads with zero value bytes if needed to achieve the specified size.
|
||||
@ -321,9 +332,17 @@ inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, co
|
||||
|
||||
void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_version) noexcept;
|
||||
|
||||
inline void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST)
|
||||
template <class T = const BasicTestingSetup>
|
||||
std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {})
|
||||
{
|
||||
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
|
||||
// Prepend default arguments for fuzzing
|
||||
const std::vector<const char*> arguments = Cat(
|
||||
{
|
||||
"-nodebuglogfile",
|
||||
},
|
||||
extra_args);
|
||||
|
||||
return std::make_unique<T>(chain_name, arguments);
|
||||
}
|
||||
|
||||
class FuzzedFileProvider
|
||||
@ -338,6 +357,7 @@ public:
|
||||
|
||||
FILE* open()
|
||||
{
|
||||
SetFuzzedErrNo(m_fuzzed_data_provider);
|
||||
if (m_fuzzed_data_provider.ConsumeBool()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -379,6 +399,7 @@ public:
|
||||
static ssize_t read(void* cookie, char* buf, size_t size)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
if (buf == nullptr || size == 0 || fuzzed_file->m_fuzzed_data_provider.ConsumeBool()) {
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||
}
|
||||
@ -397,6 +418,7 @@ public:
|
||||
static ssize_t write(void* cookie, const char* buf, size_t size)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
const ssize_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(0, size);
|
||||
if (AdditionOverflow(static_cast<ssize_t>(fuzzed_file->m_offset), n)) {
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1;
|
||||
@ -407,8 +429,9 @@ public:
|
||||
|
||||
static int seek(void* cookie, int64_t* offset, int whence)
|
||||
{
|
||||
assert(whence == SEEK_SET || whence == SEEK_CUR); // SEEK_END not implemented yet.
|
||||
assert(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END);
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
int64_t new_offset = 0;
|
||||
if (whence == SEEK_SET) {
|
||||
new_offset = *offset;
|
||||
@ -417,6 +440,12 @@ public:
|
||||
return -1;
|
||||
}
|
||||
new_offset = fuzzed_file->m_offset + *offset;
|
||||
} else if (whence == SEEK_END) {
|
||||
const int64_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 4096);
|
||||
if (AdditionOverflow(n, *offset)) {
|
||||
return -1;
|
||||
}
|
||||
new_offset = n + *offset;
|
||||
}
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
@ -429,6 +458,7 @@ public:
|
||||
static int close(void* cookie)
|
||||
{
|
||||
FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie;
|
||||
SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider);
|
||||
return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(-1, 0);
|
||||
}
|
||||
};
|
||||
|
34
src/test/fuzz/validation_load_mempool.cpp
Normal file
34
src/test/fuzz/validation_load_mempool.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 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 <chainparamsbase.h>
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <txmempool.h>
|
||||
#include <util/time.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
void initialize_validation_load_mempool()
|
||||
{
|
||||
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
|
||||
{
|
||||
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
|
||||
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
||||
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
|
||||
|
||||
CTxMemPool pool{};
|
||||
auto fuzzed_fopen = [&](const fs::path&, const char*) {
|
||||
return fuzzed_file_provider.open();
|
||||
};
|
||||
(void)LoadMempool(pool, ::ChainstateActive(), fuzzed_fopen);
|
||||
(void)DumpMempool(pool, fuzzed_fopen, true);
|
||||
}
|
352
src/test/fuzz/versionbits.cpp
Normal file
352
src/test/fuzz/versionbits.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
// Copyright (c) 2020-2021 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 <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <consensus/params.h>
|
||||
#include <primitives/block.h>
|
||||
#include <util/system.h>
|
||||
#include <versionbits.h>
|
||||
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
class TestConditionChecker : public AbstractThresholdConditionChecker
|
||||
{
|
||||
private:
|
||||
mutable ThresholdConditionCache m_cache;
|
||||
const Consensus::Params dummy_params{};
|
||||
|
||||
public:
|
||||
const int64_t m_begin;
|
||||
const int64_t m_end;
|
||||
const int m_period;
|
||||
const int m_threshold;
|
||||
const int m_bit;
|
||||
|
||||
TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit)
|
||||
: m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit}
|
||||
{
|
||||
assert(m_period > 0);
|
||||
assert(0 <= m_threshold && m_threshold <= m_period);
|
||||
assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS);
|
||||
}
|
||||
|
||||
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); }
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return m_begin; }
|
||||
int64_t EndTime(const Consensus::Params& params) const override { return m_end; }
|
||||
int Period(const Consensus::Params& params) const override { return m_period; }
|
||||
int Threshold(const Consensus::Params& params, int nAttempt) const override { return m_threshold; }
|
||||
|
||||
ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); }
|
||||
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
|
||||
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params, m_cache); }
|
||||
|
||||
bool Condition(int32_t version) const
|
||||
{
|
||||
uint32_t mask = ((uint32_t)1) << m_bit;
|
||||
return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0);
|
||||
}
|
||||
|
||||
bool Condition(const CBlockIndex* pindex) const { return Condition(pindex->nVersion); }
|
||||
};
|
||||
|
||||
/** Track blocks mined for test */
|
||||
class Blocks
|
||||
{
|
||||
private:
|
||||
std::vector<std::unique_ptr<CBlockIndex>> m_blocks;
|
||||
const uint32_t m_start_time;
|
||||
const uint32_t m_interval;
|
||||
const int32_t m_signal;
|
||||
const int32_t m_no_signal;
|
||||
|
||||
public:
|
||||
Blocks(uint32_t start_time, uint32_t interval, int32_t signal, int32_t no_signal)
|
||||
: m_start_time{start_time}, m_interval{interval}, m_signal{signal}, m_no_signal{no_signal} {}
|
||||
|
||||
size_t size() const { return m_blocks.size(); }
|
||||
|
||||
CBlockIndex* tip() const
|
||||
{
|
||||
return m_blocks.empty() ? nullptr : m_blocks.back().get();
|
||||
}
|
||||
|
||||
CBlockIndex* mine_block(bool signal)
|
||||
{
|
||||
CBlockHeader header;
|
||||
header.nVersion = signal ? m_signal : m_no_signal;
|
||||
header.nTime = m_start_time + m_blocks.size() * m_interval;
|
||||
header.nBits = 0x1d00ffff;
|
||||
|
||||
auto current_block = std::make_unique<CBlockIndex>(header);
|
||||
current_block->pprev = tip();
|
||||
current_block->nHeight = m_blocks.size();
|
||||
current_block->BuildSkip();
|
||||
|
||||
return m_blocks.emplace_back(std::move(current_block)).get();
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<const CChainParams> g_params;
|
||||
|
||||
void initialize_versionbits()
|
||||
{
|
||||
// this is actually comparatively slow, so only do it once
|
||||
g_params = CreateChainParams(CBaseChainParams::MAIN);
|
||||
assert(g_params != nullptr);
|
||||
}
|
||||
|
||||
constexpr uint32_t MAX_START_TIME = 4102444800; // 2100-01-01
|
||||
|
||||
FUZZ_TARGET_INIT(versionbits, initialize_versionbits)
|
||||
{
|
||||
const CChainParams& params = *g_params;
|
||||
const int64_t interval = params.GetConsensus().nPowTargetSpacing;
|
||||
assert(interval > 1); // need to be able to halve it
|
||||
assert(interval < std::numeric_limits<int32_t>::max());
|
||||
|
||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||
|
||||
// making period/max_periods larger slows these tests down significantly
|
||||
const int period = 32;
|
||||
const size_t max_periods = 16;
|
||||
const size_t max_blocks = 2 * period * max_periods;
|
||||
|
||||
const int threshold = fuzzed_data_provider.ConsumeIntegralInRange(1, period);
|
||||
assert(0 < threshold && threshold <= period); // must be able to both pass and fail threshold!
|
||||
|
||||
// too many blocks at 10min each might cause uint32_t time to overflow if
|
||||
// block_start_time is at the end of the range above
|
||||
assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
|
||||
|
||||
const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_START_TIME);
|
||||
|
||||
// what values for version will we use to signal / not signal?
|
||||
const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
|
||||
const int32_t ver_nosignal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
|
||||
|
||||
// select deployment parameters: bit, start time, timeout
|
||||
const int bit = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, VERSIONBITS_NUM_BITS - 1);
|
||||
|
||||
bool always_active_test = false;
|
||||
bool never_active_test = false;
|
||||
int64_t start_time;
|
||||
int64_t timeout;
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
// pick the timestamp to switch based on a block
|
||||
// note states will change *after* these blocks because mediantime lags
|
||||
int start_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, period * (max_periods - 3));
|
||||
int end_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(start_block, period * (max_periods - 3));
|
||||
|
||||
start_time = block_start_time + start_block * interval;
|
||||
timeout = block_start_time + end_block * interval;
|
||||
|
||||
assert(start_time <= timeout);
|
||||
|
||||
// allow for times to not exactly match a block
|
||||
if (fuzzed_data_provider.ConsumeBool()) start_time += interval / 2;
|
||||
if (fuzzed_data_provider.ConsumeBool()) timeout += interval / 2;
|
||||
|
||||
// this may make timeout too early; if so, don't run the test
|
||||
if (start_time > timeout) return;
|
||||
} else {
|
||||
if (fuzzed_data_provider.ConsumeBool()) {
|
||||
start_time = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
|
||||
timeout = Consensus::BIP9Deployment::NO_TIMEOUT;
|
||||
always_active_test = true;
|
||||
} else {
|
||||
start_time = 1199145601; // January 1, 2008
|
||||
timeout = 1230767999; // December 31, 2008
|
||||
never_active_test = true;
|
||||
}
|
||||
}
|
||||
|
||||
TestConditionChecker checker(start_time, timeout, period, threshold, bit);
|
||||
|
||||
// Early exit if the versions don't signal sensibly for the deployment
|
||||
if (!checker.Condition(ver_signal)) return;
|
||||
if (checker.Condition(ver_nosignal)) return;
|
||||
if (ver_nosignal < 0) return;
|
||||
|
||||
// TOP_BITS should ensure version will be positive and meet min
|
||||
// version requirement
|
||||
assert(ver_signal > 0);
|
||||
assert(ver_signal >= VERSIONBITS_LAST_OLD_BLOCK_VERSION);
|
||||
|
||||
// Now that we have chosen time and versions, setup to mine blocks
|
||||
Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
|
||||
|
||||
/* Strategy:
|
||||
* * we will mine a final period worth of blocks, with
|
||||
* randomised signalling according to a mask
|
||||
* * but before we mine those blocks, we will mine some
|
||||
* randomised number of prior periods; with either all
|
||||
* or no blocks in the period signalling
|
||||
*
|
||||
* We establish the mask first, then consume "bools" until
|
||||
* we run out of fuzz data to work out how many prior periods
|
||||
* there are and which ones will signal.
|
||||
*/
|
||||
|
||||
// establish the mask
|
||||
const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
|
||||
|
||||
// mine prior periods
|
||||
while (fuzzed_data_provider.remaining_bytes() > 0) {
|
||||
// all blocks in these periods either do or don't signal
|
||||
bool signal = fuzzed_data_provider.ConsumeBool();
|
||||
for (int b = 0; b < period; ++b) {
|
||||
blocks.mine_block(signal);
|
||||
}
|
||||
|
||||
// don't risk exceeding max_blocks or times may wrap around
|
||||
if (blocks.size() + 2 * period > max_blocks) break;
|
||||
}
|
||||
// NOTE: fuzzed_data_provider may be fully consumed at this point and should not be used further
|
||||
|
||||
// now we mine the final period and check that everything looks sane
|
||||
|
||||
// count the number of signalling blocks
|
||||
int blocks_sig = 0;
|
||||
|
||||
// get the info for the first block of the period
|
||||
CBlockIndex* prev = blocks.tip();
|
||||
const int exp_since = checker.GetStateSinceHeightFor(prev);
|
||||
const ThresholdState exp_state = checker.GetStateFor(prev);
|
||||
BIP9Stats last_stats = checker.GetStateStatisticsFor(prev);
|
||||
|
||||
int prev_next_height = (prev == nullptr ? 0 : prev->nHeight + 1);
|
||||
assert(exp_since <= prev_next_height);
|
||||
|
||||
// mine (period-1) blocks and check state
|
||||
for (int b = 1; b < period; ++b) {
|
||||
const bool signal = (signalling_mask >> (b % 32)) & 1;
|
||||
if (signal) ++blocks_sig;
|
||||
|
||||
CBlockIndex* current_block = blocks.mine_block(signal);
|
||||
|
||||
// verify that signalling attempt was interpreted correctly
|
||||
assert(checker.Condition(current_block) == signal);
|
||||
|
||||
// state and since don't change within the period
|
||||
const ThresholdState state = checker.GetStateFor(current_block);
|
||||
const int since = checker.GetStateSinceHeightFor(current_block);
|
||||
assert(state == exp_state);
|
||||
assert(since == exp_since);
|
||||
|
||||
// GetStateStatistics may crash when state is not STARTED
|
||||
if (state != ThresholdState::STARTED) continue;
|
||||
|
||||
// check that after mining this block stats change as expected
|
||||
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
||||
assert(stats.period == period);
|
||||
assert(stats.threshold == threshold);
|
||||
assert(stats.elapsed == b);
|
||||
assert(stats.count == last_stats.count + (signal ? 1 : 0));
|
||||
assert(stats.possible == (stats.count + period >= stats.elapsed + threshold));
|
||||
last_stats = stats;
|
||||
}
|
||||
|
||||
if (exp_state == ThresholdState::STARTED) {
|
||||
// double check that stats.possible is sane
|
||||
if (blocks_sig >= threshold - 1) assert(last_stats.possible);
|
||||
}
|
||||
|
||||
// mine the final block
|
||||
bool signal = (signalling_mask >> (period % 32)) & 1;
|
||||
if (signal) ++blocks_sig;
|
||||
CBlockIndex* current_block = blocks.mine_block(signal);
|
||||
assert(checker.Condition(current_block) == signal);
|
||||
|
||||
// GetStateStatistics is safe on a period boundary
|
||||
// and has progressed to a new period
|
||||
const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
|
||||
assert(stats.period == period);
|
||||
assert(stats.threshold == threshold);
|
||||
assert(stats.elapsed == 0);
|
||||
assert(stats.count == 0);
|
||||
assert(stats.possible == true);
|
||||
|
||||
// More interesting is whether the state changed.
|
||||
const ThresholdState state = checker.GetStateFor(current_block);
|
||||
const int since = checker.GetStateSinceHeightFor(current_block);
|
||||
|
||||
// since is straightforward:
|
||||
assert(since % period == 0);
|
||||
assert(0 <= since && since <= current_block->nHeight + 1);
|
||||
if (state == exp_state) {
|
||||
assert(since == exp_since);
|
||||
} else {
|
||||
assert(since == current_block->nHeight + 1);
|
||||
}
|
||||
|
||||
// state is where everything interesting is
|
||||
switch (state) {
|
||||
case ThresholdState::DEFINED:
|
||||
assert(since == 0);
|
||||
assert(exp_state == ThresholdState::DEFINED);
|
||||
assert(current_block->GetMedianTimePast() < checker.m_begin);
|
||||
assert(current_block->GetMedianTimePast() < checker.m_end);
|
||||
break;
|
||||
case ThresholdState::STARTED:
|
||||
assert(current_block->GetMedianTimePast() >= checker.m_begin);
|
||||
assert(current_block->GetMedianTimePast() < checker.m_end);
|
||||
if (exp_state == ThresholdState::STARTED) {
|
||||
assert(blocks_sig < threshold);
|
||||
} else {
|
||||
assert(exp_state == ThresholdState::DEFINED);
|
||||
}
|
||||
break;
|
||||
case ThresholdState::LOCKED_IN:
|
||||
assert(exp_state == ThresholdState::STARTED);
|
||||
assert(current_block->GetMedianTimePast() < checker.m_end);
|
||||
assert(blocks_sig >= threshold);
|
||||
break;
|
||||
case ThresholdState::ACTIVE:
|
||||
assert(exp_state == ThresholdState::ACTIVE || exp_state == ThresholdState::LOCKED_IN);
|
||||
break;
|
||||
case ThresholdState::FAILED:
|
||||
assert(current_block->GetMedianTimePast() >= checker.m_end);
|
||||
assert(exp_state != ThresholdState::LOCKED_IN && exp_state != ThresholdState::ACTIVE);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (blocks.size() >= period * max_periods) {
|
||||
// we chose the timeout (and block times) so that by the time we have this many blocks it's all over
|
||||
assert(state == ThresholdState::ACTIVE || state == ThresholdState::FAILED);
|
||||
}
|
||||
|
||||
// "always active" has additional restrictions
|
||||
if (always_active_test) {
|
||||
assert(state == ThresholdState::ACTIVE);
|
||||
assert(exp_state == ThresholdState::ACTIVE);
|
||||
assert(since == 0);
|
||||
} else {
|
||||
// except for always active, the initial state is always DEFINED
|
||||
assert(since > 0 || state == ThresholdState::DEFINED);
|
||||
assert(exp_since > 0 || exp_state == ThresholdState::DEFINED);
|
||||
}
|
||||
|
||||
// "never active" does too
|
||||
if (never_active_test) {
|
||||
assert(state == ThresholdState::FAILED);
|
||||
assert(since == period);
|
||||
if (exp_since == 0) {
|
||||
assert(exp_state == ThresholdState::DEFINED);
|
||||
} else {
|
||||
assert(exp_state == ThresholdState::FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
m_node.mempool->clear();
|
||||
|
||||
// orphan in *m_node.mempool, template creation fails
|
||||
// orphan in mempool, template creation fails
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
|
||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
||||
@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
m_node.mempool->clear();
|
||||
|
||||
// coinbase in *m_node.mempool, template creation fails
|
||||
// coinbase in mempool, template creation fails
|
||||
tx.vin.resize(1);
|
||||
tx.vin[0].prevout.SetNull();
|
||||
tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
|
||||
@ -369,25 +369,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
|
||||
m_node.mempool->clear();
|
||||
|
||||
// invalid (pre-p2sh) txn in *m_node.mempool, template creation fails
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vin[0].scriptSig = CScript() << OP_1;
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
|
||||
script = CScript() << OP_0;
|
||||
tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||
// Should throw block-validation-failed
|
||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
|
||||
m_node.mempool->clear();
|
||||
|
||||
// double spend txn pair in *m_node.mempool, template creation fails
|
||||
// double spend txn pair in mempool, template creation fails
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].scriptSig = CScript() << OP_1;
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
|
||||
@ -426,6 +408,25 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||
// ::ChainActive().SetTip(next);
|
||||
// }
|
||||
//BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
|
||||
|
||||
// invalid (pre-p2sh) txn in mempool, template creation fails
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vin[0].scriptSig = CScript() << OP_1;
|
||||
tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
|
||||
script = CScript() << OP_0;
|
||||
tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
hash = tx.GetHash();
|
||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||
// Should throw block-validation-failed
|
||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
|
||||
m_node.mempool->clear();
|
||||
|
||||
// // Delete the dummy blocks again.
|
||||
// while (::ChainActive().Tip()->nHeight > nHeight) {
|
||||
// CBlockIndex* del = ::ChainActive().Tip();
|
||||
|
@ -32,6 +32,12 @@ public:
|
||||
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); }
|
||||
};
|
||||
|
||||
class TestAlwaysActiveConditionChecker : public TestConditionChecker
|
||||
{
|
||||
public:
|
||||
int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; }
|
||||
};
|
||||
|
||||
#define CHECKERS 6
|
||||
|
||||
class VersionBitsTester
|
||||
@ -43,6 +49,8 @@ class VersionBitsTester
|
||||
// The first one performs all checks, the second only 50%, the third only 25%, etc...
|
||||
// This is to test whether lack of cached information leads to the same results.
|
||||
TestConditionChecker checker[CHECKERS];
|
||||
// Another 6 that assume always active activation
|
||||
TestAlwaysActiveConditionChecker checker_always[CHECKERS];
|
||||
|
||||
// Test counter (to identify failures)
|
||||
int num;
|
||||
@ -56,6 +64,7 @@ public:
|
||||
}
|
||||
for (unsigned int i = 0; i < CHECKERS; i++) {
|
||||
checker[i] = TestConditionChecker();
|
||||
checker_always[i] = TestAlwaysActiveConditionChecker();
|
||||
}
|
||||
vpblock.clear();
|
||||
return *this;
|
||||
@ -82,6 +91,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
@ -92,6 +102,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::DEFINED, strprintf("Test %i for DEFINED", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
@ -102,6 +113,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::STARTED, strprintf("Test %i for STARTED", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
@ -112,6 +124,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
@ -122,6 +135,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
@ -132,6 +146,7 @@ public:
|
||||
for (int i = 0; i < CHECKERS; i++) {
|
||||
if (InsecureRandBits(i) == 0) {
|
||||
BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::FAILED, strprintf("Test %i for FAILED", num));
|
||||
BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
|
||||
}
|
||||
}
|
||||
num++;
|
||||
|
@ -52,77 +52,6 @@ static const int MAX_LINE_LENGTH = 100000;
|
||||
|
||||
/****** Low-level TorControlConnection ********/
|
||||
|
||||
/** Reply from Tor, can be single or multi-line */
|
||||
class TorControlReply
|
||||
{
|
||||
public:
|
||||
TorControlReply() { Clear(); }
|
||||
|
||||
int code;
|
||||
std::vector<std::string> lines;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
code = 0;
|
||||
lines.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/** Low-level handling for Tor control connection.
|
||||
* Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
|
||||
*/
|
||||
class TorControlConnection
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(TorControlConnection&)> ConnectionCB;
|
||||
typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB;
|
||||
|
||||
/** Create a new TorControlConnection.
|
||||
*/
|
||||
explicit TorControlConnection(struct event_base *base);
|
||||
~TorControlConnection();
|
||||
|
||||
/**
|
||||
* Connect to a Tor control port.
|
||||
* tor_control_center is address of the form host:port.
|
||||
* connected is the handler that is called when connection is successfully established.
|
||||
* disconnected is a handler that is called when the connection is broken.
|
||||
* Return true on success.
|
||||
*/
|
||||
bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
|
||||
|
||||
/**
|
||||
* Disconnect from Tor control port.
|
||||
*/
|
||||
void Disconnect();
|
||||
|
||||
/** Send a command, register a handler for the reply.
|
||||
* A trailing CRLF is automatically added.
|
||||
* Return true on success.
|
||||
*/
|
||||
bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler);
|
||||
|
||||
/** Response handlers for async replies */
|
||||
boost::signals2::signal<void(TorControlConnection &,const TorControlReply &)> async_handler;
|
||||
private:
|
||||
/** Callback when ready for use */
|
||||
std::function<void(TorControlConnection&)> connected;
|
||||
/** Callback when connection lost */
|
||||
std::function<void(TorControlConnection&)> disconnected;
|
||||
/** Libevent event base */
|
||||
struct event_base *base;
|
||||
/** Connection to control socket */
|
||||
struct bufferevent *b_conn;
|
||||
/** Message being received */
|
||||
TorControlReply message;
|
||||
/** Response handlers */
|
||||
std::deque<ReplyHandlerCB> reply_handlers;
|
||||
|
||||
/** Libevent handlers: internal */
|
||||
static void readcb(struct bufferevent *bev, void *ctx);
|
||||
static void eventcb(struct bufferevent *bev, short what, void *ctx);
|
||||
};
|
||||
|
||||
TorControlConnection::TorControlConnection(struct event_base *_base):
|
||||
base(_base), b_conn(nullptr)
|
||||
{
|
||||
@ -366,55 +295,6 @@ std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/****** Bitcoin specific TorController implementation ********/
|
||||
|
||||
/** Controller that connects to Tor control socket, authenticate, then create
|
||||
* and maintain an ephemeral onion service.
|
||||
*/
|
||||
class TorController
|
||||
{
|
||||
public:
|
||||
TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
|
||||
~TorController();
|
||||
|
||||
/** Get name of file to store private key in */
|
||||
fs::path GetPrivateKeyFile();
|
||||
|
||||
/** Reconnect, after getting disconnected */
|
||||
void Reconnect();
|
||||
private:
|
||||
struct event_base* base;
|
||||
const std::string m_tor_control_center;
|
||||
TorControlConnection conn;
|
||||
std::string private_key;
|
||||
std::string service_id;
|
||||
bool reconnect;
|
||||
struct event *reconnect_ev;
|
||||
float reconnect_timeout;
|
||||
CService service;
|
||||
const CService m_target;
|
||||
/** Cookie for SAFECOOKIE auth */
|
||||
std::vector<uint8_t> cookie;
|
||||
/** ClientNonce for SAFECOOKIE auth */
|
||||
std::vector<uint8_t> clientNonce;
|
||||
|
||||
/** Callback for ADD_ONION result */
|
||||
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHENTICATE result */
|
||||
void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHCHALLENGE result */
|
||||
void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for PROTOCOLINFO result */
|
||||
void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback after successful connection */
|
||||
void connected_cb(TorControlConnection& conn);
|
||||
/** Callback after connection lost or failed connection attempt */
|
||||
void disconnected_cb(TorControlConnection& conn);
|
||||
|
||||
/** Callback for reconnect timer */
|
||||
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
||||
};
|
||||
|
||||
TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target):
|
||||
base(_base),
|
||||
m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_ev(0),
|
||||
|
136
src/torcontrol.h
136
src/torcontrol.h
@ -8,7 +8,19 @@
|
||||
#ifndef BITCOIN_TORCONTROL_H
|
||||
#define BITCOIN_TORCONTROL_H
|
||||
|
||||
#include <fs.h>
|
||||
#include <netaddress.h>
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/event.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CService;
|
||||
|
||||
@ -21,4 +33,128 @@ void StopTorControl();
|
||||
|
||||
CService DefaultOnionServiceTarget();
|
||||
|
||||
/** Reply from Tor, can be single or multi-line */
|
||||
class TorControlReply
|
||||
{
|
||||
public:
|
||||
TorControlReply() { Clear(); }
|
||||
|
||||
int code;
|
||||
std::vector<std::string> lines;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
code = 0;
|
||||
lines.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/** Low-level handling for Tor control connection.
|
||||
* Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
|
||||
*/
|
||||
class TorControlConnection
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(TorControlConnection&)> ConnectionCB;
|
||||
typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB;
|
||||
|
||||
/** Create a new TorControlConnection.
|
||||
*/
|
||||
explicit TorControlConnection(struct event_base *base);
|
||||
~TorControlConnection();
|
||||
|
||||
/**
|
||||
* Connect to a Tor control port.
|
||||
* tor_control_center is address of the form host:port.
|
||||
* connected is the handler that is called when connection is successfully established.
|
||||
* disconnected is a handler that is called when the connection is broken.
|
||||
* Return true on success.
|
||||
*/
|
||||
bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
|
||||
|
||||
/**
|
||||
* Disconnect from Tor control port.
|
||||
*/
|
||||
void Disconnect();
|
||||
|
||||
/** Send a command, register a handler for the reply.
|
||||
* A trailing CRLF is automatically added.
|
||||
* Return true on success.
|
||||
*/
|
||||
bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler);
|
||||
|
||||
/** Response handlers for async replies */
|
||||
boost::signals2::signal<void(TorControlConnection &,const TorControlReply &)> async_handler;
|
||||
private:
|
||||
/** Callback when ready for use */
|
||||
std::function<void(TorControlConnection&)> connected;
|
||||
/** Callback when connection lost */
|
||||
std::function<void(TorControlConnection&)> disconnected;
|
||||
/** Libevent event base */
|
||||
struct event_base *base;
|
||||
/** Connection to control socket */
|
||||
struct bufferevent *b_conn;
|
||||
/** Message being received */
|
||||
TorControlReply message;
|
||||
/** Response handlers */
|
||||
std::deque<ReplyHandlerCB> reply_handlers;
|
||||
|
||||
/** Libevent handlers: internal */
|
||||
static void readcb(struct bufferevent *bev, void *ctx);
|
||||
static void eventcb(struct bufferevent *bev, short what, void *ctx);
|
||||
};
|
||||
|
||||
/****** Bitcoin specific TorController implementation ********/
|
||||
|
||||
/** Controller that connects to Tor control socket, authenticate, then create
|
||||
* and maintain an ephemeral onion service.
|
||||
*/
|
||||
class TorController
|
||||
{
|
||||
public:
|
||||
TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
|
||||
TorController() : conn{nullptr} {
|
||||
// Used for testing only.
|
||||
}
|
||||
~TorController();
|
||||
|
||||
/** Get name of file to store private key in */
|
||||
fs::path GetPrivateKeyFile();
|
||||
|
||||
/** Reconnect, after getting disconnected */
|
||||
void Reconnect();
|
||||
private:
|
||||
struct event_base* base;
|
||||
const std::string m_tor_control_center;
|
||||
TorControlConnection conn;
|
||||
std::string private_key;
|
||||
std::string service_id;
|
||||
bool reconnect;
|
||||
struct event *reconnect_ev = nullptr;
|
||||
float reconnect_timeout;
|
||||
CService service;
|
||||
const CService m_target;
|
||||
/** Cookie for SAFECOOKIE auth */
|
||||
std::vector<uint8_t> cookie;
|
||||
/** ClientNonce for SAFECOOKIE auth */
|
||||
std::vector<uint8_t> clientNonce;
|
||||
|
||||
public:
|
||||
/** Callback for ADD_ONION result */
|
||||
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHENTICATE result */
|
||||
void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHCHALLENGE result */
|
||||
void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for PROTOCOLINFO result */
|
||||
void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback after successful connection */
|
||||
void connected_cb(TorControlConnection& conn);
|
||||
/** Callback after connection lost or failed connection attempt */
|
||||
void disconnected_cb(TorControlConnection& conn);
|
||||
|
||||
/** Callback for reconnect timer */
|
||||
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
||||
};
|
||||
|
||||
#endif /* BITCOIN_TORCONTROL_H */
|
||||
|
@ -1966,11 +1966,12 @@ static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_
|
||||
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
// BIP16 didn't become active until Apr 1 2012
|
||||
int64_t nBIP16SwitchTime = 1333238400;
|
||||
bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime);
|
||||
unsigned int flags = SCRIPT_VERIFY_NONE;
|
||||
|
||||
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
|
||||
// Start enforcing P2SH (BIP16)
|
||||
if (pindex->nHeight >= consensusparams.BIP16Height) {
|
||||
flags |= SCRIPT_VERIFY_P2SH;
|
||||
}
|
||||
|
||||
// Start enforcing the DERSIG (BIP66) rule
|
||||
if (pindex->nHeight >= consensusparams.BIP66Height) {
|
||||
@ -5507,11 +5508,11 @@ CBlockFileInfo* GetBlockFileInfo(size_t n)
|
||||
|
||||
static const uint64_t MEMPOOL_DUMP_VERSION = 1;
|
||||
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate)
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
|
||||
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb");
|
||||
FILE* filestr{mockable_fopen_function(GetDataDir() / "mempool.dat", "rb")};
|
||||
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
|
||||
if (file.IsNull()) {
|
||||
LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
|
||||
@ -5601,7 +5602,7 @@ bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DumpMempool(const CTxMemPool& pool)
|
||||
bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function, bool skip_file_commit)
|
||||
{
|
||||
int64_t start = GetTimeMicros();
|
||||
|
||||
@ -5624,7 +5625,7 @@ bool DumpMempool(const CTxMemPool& pool)
|
||||
int64_t mid = GetTimeMicros();
|
||||
|
||||
try {
|
||||
FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb");
|
||||
FILE* filestr{mockable_fopen_function(GetDataDir() / "mempool.dat.new", "wb")};
|
||||
if (!filestr) {
|
||||
return false;
|
||||
}
|
||||
@ -5647,7 +5648,7 @@ bool DumpMempool(const CTxMemPool& pool)
|
||||
LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
|
||||
file << unbroadcast_txids;
|
||||
|
||||
if (!FileCommit(file.Get()))
|
||||
if (!skip_file_commit && !FileCommit(file.Get()))
|
||||
throw std::runtime_error("FileCommit failed");
|
||||
file.fclose();
|
||||
if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat")) {
|
||||
|
@ -1087,11 +1087,13 @@ bool GetBlockHash(uint256& hashRet, int nBlockHeight = -1);
|
||||
/** Get block file info entry for one block file */
|
||||
CBlockFileInfo* GetBlockFileInfo(size_t n);
|
||||
|
||||
using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
|
||||
|
||||
/** Dump the mempool to disk. */
|
||||
bool DumpMempool(const CTxMemPool& pool);
|
||||
bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function = fsbridge::fopen, bool skip_file_commit = false);
|
||||
|
||||
/** Load the mempool from disk. */
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate);
|
||||
bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function = fsbridge::fopen);
|
||||
|
||||
//! Check whether the block associated with this index entry is pruned or not.
|
||||
inline bool IsBlockPruned(const CBlockIndex* pblockindex)
|
||||
|
@ -11,6 +11,11 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
|
||||
int64_t nTimeStart = BeginTime(params);
|
||||
int64_t nTimeTimeout = EndTime(params);
|
||||
|
||||
// Check if this deployment is always active.
|
||||
if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
|
||||
return ThresholdState::ACTIVE;
|
||||
}
|
||||
|
||||
// A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
|
||||
if (pindexPrev != nullptr) {
|
||||
pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
|
||||
@ -161,6 +166,11 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
|
||||
|
||||
int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
|
||||
{
|
||||
int64_t start_time = BeginTime(params);
|
||||
if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
|
||||
|
||||
// BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
|
||||
|
@ -145,7 +145,7 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
'bip9': {
|
||||
'status': 'defined',
|
||||
'start_time': 0,
|
||||
'timeout': 999999999999,
|
||||
'timeout': 9223372036854775807,
|
||||
'since': 0
|
||||
}, 'active': False},
|
||||
'mn_rr': {
|
||||
@ -153,7 +153,7 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
'bip9': {
|
||||
'status': 'defined',
|
||||
'start_time': 0,
|
||||
'timeout': 999999999999,
|
||||
'timeout': 9223372036854775807,
|
||||
'since': 0
|
||||
},
|
||||
'active': False},
|
||||
@ -163,7 +163,7 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
'status': 'started',
|
||||
'bit': 28,
|
||||
'start_time': 0,
|
||||
'timeout': 999999999999, # testdummy does not have a timeout so is set to the max int64 value
|
||||
'timeout': 9223372036854775807, # testdummy does not have a timeout so is set to the max int64 value
|
||||
'since': 144,
|
||||
'statistics': {
|
||||
'period': 144,
|
||||
|
Loading…
Reference in New Issue
Block a user