aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Jahr <fjahr@protonmail.com>2024-03-31 23:50:42 +0200
committerFabian Jahr <fjahr@protonmail.com>2024-08-06 01:38:10 +0200
commit74a04f9e7ad6a16988149cc3438b9ce13c91cdb9 (patch)
treeb9db7fb3b361d76c8f60a0af1b13239d4b1aabbd
parent902dd14382256c9d33bce667795a64079f3bee6b (diff)
testnet: Introduce Testnet4
-rw-r--r--contrib/completions/bash/bitcoin-cli.bash2
-rwxr-xr-xcontrib/seeds/generate-seeds.py6
-rw-r--r--doc/REST-interface.md2
-rw-r--r--doc/files.md13
-rw-r--r--doc/release-process.md4
-rw-r--r--src/bitcoin-cli.cpp5
-rw-r--r--src/bitcoin-wallet.cpp2
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/chainparamsbase.cpp7
-rw-r--r--src/chainparamsseeds.h12
-rw-r--r--src/common/args.cpp7
-rw-r--r--src/common/args.h2
-rw-r--r--src/consensus/params.h1
-rw-r--r--src/init.cpp17
-rw-r--r--src/kernel/chainparams.cpp107
-rw-r--r--src/kernel/chainparams.h1
-rw-r--r--src/qt/guiconstants.h1
-rw-r--r--src/qt/guiutil.cpp1
-rw-r--r--src/qt/networkstyle.cpp1
-rw-r--r--src/test/argsman_tests.cpp18
-rw-r--r--src/test/pow_tests.cpp5
-rw-r--r--src/test/versionbits_tests.cpp2
-rw-r--r--src/util/chaintype.cpp4
-rw-r--r--src/util/chaintype.h1
-rwxr-xr-xtest/functional/feature_config_args.py36
-rwxr-xr-xtest/functional/wallet_crosschain.py29
26 files changed, 258 insertions, 30 deletions
diff --git a/contrib/completions/bash/bitcoin-cli.bash b/contrib/completions/bash/bitcoin-cli.bash
index 89e01bc09a..b04fdbcb0e 100644
--- a/contrib/completions/bash/bitcoin-cli.bash
+++ b/contrib/completions/bash/bitcoin-cli.bash
@@ -9,7 +9,7 @@ _bitcoin_rpc() {
local rpcargs=()
for i in ${COMP_LINE}; do
case "$i" in
- -conf=*|-datadir=*|-regtest|-rpc*|-testnet)
+ -conf=*|-datadir=*|-regtest|-rpc*|-testnet|-testnet4)
rpcargs=( "${rpcargs[@]}" "$i" )
;;
esac
diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py
index f67e7b0f4c..72dd5d28cc 100755
--- a/contrib/seeds/generate-seeds.py
+++ b/contrib/seeds/generate-seeds.py
@@ -5,11 +5,12 @@
'''
Script to generate list of seed nodes for kernel/chainparams.cpp.
-This script expects two text files in the directory that is passed as an
+This script expects three text files in the directory that is passed as an
argument:
nodes_main.txt
nodes_test.txt
+ nodes_testnet4.txt
These files must consist of lines in the format
@@ -171,6 +172,9 @@ def main():
g.write('\n')
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
process_nodes(g, f, 'chainparams_seed_test')
+ g.write('\n')
+ with open(os.path.join(indir,'nodes_testnet4.txt'), 'r', encoding="utf8") as f:
+ process_nodes(g, f, 'chainparams_seed_testnet4')
g.write('#endif // BITCOIN_CHAINPARAMSSEEDS_H\n')
if __name__ == '__main__':
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index 2d7d0e3769..6664bc2a3a 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -4,7 +4,7 @@ Unauthenticated REST Interface
The REST API can be enabled with the `-rest` option.
The interface runs on the same port as the JSON-RPC interface, by default port 8332 for mainnet, port 18332 for testnet,
-port 38332 for signet, and port 18443 for regtest.
+port 48332 for testnet4, port 38332 for signet, and port 18443 for regtest.
REST Interface consistency guarantees
-------------------------------------
diff --git a/doc/files.md b/doc/files.md
index 03e52f02c9..dd16548df5 100644
--- a/doc/files.md
+++ b/doc/files.md
@@ -34,12 +34,13 @@ Windows | `%LOCALAPPDATA%\Bitcoin\` <sup>[\[1\]](#note1)</sup>
3. All content of the data directory, except for `bitcoin.conf` file, is chain-specific. This means the actual data directory paths for non-mainnet cases differ:
-Chain option | Data directory path
--------------------------------|------------------------------
-`-chain=main` (default) | *path_to_datadir*`/`
-`-chain=test` or `-testnet` | *path_to_datadir*`/testnet3/`
-`-chain=signet` or `-signet` | *path_to_datadir*`/signet/`
-`-chain=regtest` or `-regtest` | *path_to_datadir*`/regtest/`
+Chain option | Data directory path
+---------------------------------|------------------------------
+`-chain=main` (default) | *path_to_datadir*`/`
+`-chain=test` or `-testnet` | *path_to_datadir*`/testnet3/`
+`-chain=testnet4` or `-testnet4` | *path_to_datadir*`/testnet4/`
+`-chain=signet` or `-signet` | *path_to_datadir*`/signet/`
+`-chain=regtest` or `-regtest` | *path_to_datadir*`/regtest/`
## Data directory layout
diff --git a/doc/release-process.md b/doc/release-process.md
index 1e6d49100e..fa2c53eb0c 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -311,13 +311,15 @@ Both variables are used as a guideline for how much space the user needs on thei
Note that all values should be taken from a **fully synced** node and have an overhead of 5-10% added on top of its base value.
To calculate `m_assumed_blockchain_size`, take the size in GiB of these directories:
-- For `mainnet` -> the data directory, excluding the `/testnet3`, `/signet`, and `/regtest` directories and any overly large files, e.g. a huge `debug.log`
+- For `mainnet` -> the data directory, excluding the `/testnet3`, `/testnet4`, `/signet`, and `/regtest` directories and any overly large files, e.g. a huge `debug.log`
- For `testnet` -> `/testnet3`
+- For `testnet4` -> `/testnet4`
- For `signet` -> `/signet`
To calculate `m_assumed_chain_state_size`, take the size in GiB of these directories:
- For `mainnet` -> `/chainstate`
- For `testnet` -> `/testnet3/chainstate`
+- For `testnet4` -> `/testnet4/chainstate`
- For `signet` -> `/signet/chainstate`
Notes:
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 44fc273163..934b5fb6dc 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -75,6 +75,7 @@ static void SetupCliArgs(ArgsManager& argsman)
const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
+ const auto testnet4BaseParams = CreateBaseChainParams(ChainType::TESTNET4);
const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
@@ -98,7 +99,7 @@ static void SetupCliArgs(ArgsManager& argsman)
argsman.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u, testnet: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u, testnet: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpcwait", "Wait for RPC server to start", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpcwaittimeout=<n>", strprintf("Timeout in seconds to wait for the RPC server to start, or 0 for no timeout. (default: %d)", DEFAULT_WAIT_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
@@ -428,6 +429,8 @@ private:
std::string ChainToString() const
{
switch (gArgs.GetChainType()) {
+ case ChainType::TESTNET4:
+ return " testnet4";
case ChainType::TESTNET:
return " testnet";
case ChainType::SIGNET:
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index b6f5c3f15d..7d030abe97 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -69,7 +69,7 @@ static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[
strUsage += "\n"
"bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n"
"By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n"
- "To change the target wallet, use the -datadir, -wallet and -regtest/-signet/-testnet arguments.\n\n"
+ "To change the target wallet, use the -datadir, -wallet and -regtest/-signet/-testnet/-testnet4 arguments.\n\n"
"Usage:\n"
" bitcoin-wallet [options] <command>\n";
strUsage += "\n" + args.GetHelpMessage();
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 5d4401b719..68319e8e8b 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -115,6 +115,8 @@ std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, c
return CChainParams::Main();
case ChainType::TESTNET:
return CChainParams::TestNet();
+ case ChainType::TESTNET4:
+ return CChainParams::TestNet4();
case ChainType::SIGNET: {
auto opts = CChainParams::SigNetOptions{};
ReadSigNetArgs(args, opts);
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 8cbf9e85e0..2b57b4ca55 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -17,7 +17,8 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman)
argsman.AddArg("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
"This is intended for regression testing tools and app development. Equivalent to -chain=regtest.", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (segwit, bip34, dersig, cltv, csv). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-testnet", "Use the test chain. Equivalent to -chain=test.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
+ argsman.AddArg("-testnet", "Use the testnet3 chain. Equivalent to -chain=test. Support for testnet3 is deprecated and will be removed with the next release. Consider moving to testnet4 now by using -testnet4.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
+ argsman.AddArg("-testnet4", "Use the testnet4 chain. Equivalent to -chain=testnet4.", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-vbparams=deployment:start:end[:min_activation_height]", "Use given start/end times and min_activation_height for specified version bits deployment (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-signet", "Use the signet chain. Equivalent to -chain=signet. Note that the network is defined by the -signetchallenge parameter", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
argsman.AddArg("-signetchallenge", "Blocks must satisfy the given script to be considered valid (only for signet networks; defaults to the global default signet test network challenge)", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::CHAINPARAMS);
@@ -33,7 +34,7 @@ const CBaseChainParams& BaseParams()
}
/**
- * Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have
+ * Port numbers for incoming Tor connections (8334, 18334, 38334, 48334, 18445) have
* been chosen arbitrarily to keep ranges of used ports tight.
*/
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const ChainType chain)
@@ -43,6 +44,8 @@ std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const ChainType chain)
return std::make_unique<CBaseChainParams>("", 8332, 8334);
case ChainType::TESTNET:
return std::make_unique<CBaseChainParams>("testnet3", 18332, 18334);
+ case ChainType::TESTNET4:
+ return std::make_unique<CBaseChainParams>("testnet4", 48332, 48334);
case ChainType::SIGNET:
return std::make_unique<CBaseChainParams>("signet", 38332, 38334);
case ChainType::REGTEST:
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index 554d0cae5a..2a7e52316a 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -1786,4 +1786,16 @@ static const uint8_t chainparams_seed_test[] = {
0x04,0x20,0xbd,0x0e,0xc8,0x73,0x43,0xa7,0xc6,0x25,0x15,0xcf,0x3e,0x23,0xa8,0xb0,0xbf,0xe8,0x20,0xa7,0xec,0x2a,0xf6,0x37,0x6c,0x60,0x5e,0x4d,0xed,0xf4,0xb1,0xef,0xf7,0xb2,0x47,0x9d,
0x04,0x20,0xc8,0x88,0xfe,0x71,0x5f,0xa3,0x6c,0x96,0x6a,0xd7,0x9e,0x38,0x84,0x9f,0x44,0xe1,0x6b,0xdc,0x98,0x31,0xad,0x96,0x29,0xe7,0x00,0x83,0x63,0x03,0xae,0x69,0x2e,0x63,0x47,0x9d,
};
+
+static const uint8_t chainparams_seed_testnet4[] = {
+ 0x01,0x04,0x39,0x80,0xb0,0xa3,0xbc,0xcd,
+ 0x01,0x04,0x33,0x9e,0xf8,0x08,0xbc,0xcd,
+ 0x01,0x04,0x5f,0xd9,0x49,0xa2,0xbc,0xcd,
+ 0x01,0x04,0x12,0xbd,0x9c,0x66,0xbc,0xcd,
+ 0x01,0x04,0x67,0x63,0xab,0xd4,0xbc,0xcd,
+ 0x01,0x04,0x52,0x43,0x66,0x0f,0xbc,0xcd,
+ 0x01,0x04,0x58,0x63,0xf8,0x32,0xbc,0xcd,
+ 0x01,0x04,0x67,0xa5,0xc0,0xd2,0xbc,0xcd,
+ 0x01,0x04,0x12,0xc9,0xcf,0x37,0xbc,0xcd,
+};
#endif // BITCOIN_CHAINPARAMSSEEDS_H
diff --git a/src/common/args.cpp b/src/common/args.cpp
index caff36fdb3..a37a16b62b 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -159,6 +159,7 @@ std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
ChainTypeToString(ChainType::REGTEST),
ChainTypeToString(ChainType::SIGNET),
ChainTypeToString(ChainType::TESTNET),
+ ChainTypeToString(ChainType::TESTNET4),
ChainTypeToString(ChainType::MAIN),
};
@@ -773,10 +774,11 @@ std::variant<ChainType, std::string> ArgsManager::GetChainArg() const
const bool fRegTest = get_net("-regtest");
const bool fSigNet = get_net("-signet");
const bool fTestNet = get_net("-testnet");
+ const bool fTestNet4 = get_net("-testnet4");
const auto chain_arg = GetArg("-chain");
- if ((int)chain_arg.has_value() + (int)fRegTest + (int)fSigNet + (int)fTestNet > 1) {
- throw std::runtime_error("Invalid combination of -regtest, -signet, -testnet and -chain. Can use at most one.");
+ if ((int)chain_arg.has_value() + (int)fRegTest + (int)fSigNet + (int)fTestNet + (int)fTestNet4 > 1) {
+ throw std::runtime_error("Invalid combination of -regtest, -signet, -testnet, -testnet4 and -chain. Can use at most one.");
}
if (chain_arg) {
if (auto parsed = ChainTypeFromString(*chain_arg)) return *parsed;
@@ -786,6 +788,7 @@ std::variant<ChainType, std::string> ArgsManager::GetChainArg() const
if (fRegTest) return ChainType::REGTEST;
if (fSigNet) return ChainType::SIGNET;
if (fTestNet) return ChainType::TESTNET;
+ if (fTestNet4) return ChainType::TESTNET4;
return ChainType::MAIN;
}
diff --git a/src/common/args.h b/src/common/args.h
index 78a61313b9..323a86d8dc 100644
--- a/src/common/args.h
+++ b/src/common/args.h
@@ -423,7 +423,7 @@ private:
fs::path GetDataDir(bool net_specific) const;
/**
- * Return -regtest/-signet/-testnet/-chain= setting as a ChainType enum if a
+ * Return -regtest/-signet/-testnet/-testnet4/-chain= setting as a ChainType enum if a
* recognized chain type was set, or as a string if an unrecognized chain
* name was set. Raise an exception if an invalid combination of flags was
* provided.
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 25f53eb620..d970e41637 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -108,6 +108,7 @@ struct Params {
/** Proof of work parameters */
uint256 powLimit;
bool fPowAllowMinDifficultyBlocks;
+ bool enforce_BIP94;
bool fPowNoRetargeting;
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
diff --git a/src/init.cpp b/src/init.cpp
index 9e570d6128..8c5e1f0037 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -450,10 +450,12 @@ void SetupServerArgs(ArgsManager& argsman)
const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
+ const auto testnet4BaseParams = CreateBaseChainParams(ChainType::TESTNET4);
const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
const auto defaultChainParams = CreateChainParams(argsman, ChainType::MAIN);
const auto testnetChainParams = CreateChainParams(argsman, ChainType::TESTNET);
+ const auto testnet4ChainParams = CreateChainParams(argsman, ChainType::TESTNET4);
const auto signetChainParams = CreateChainParams(argsman, ChainType::SIGNET);
const auto regtestChainParams = CreateChainParams(argsman, ChainType::REGTEST);
@@ -467,7 +469,7 @@ void SetupServerArgs(ArgsManager& argsman)
#if HAVE_SYSTEM
argsman.AddArg("-alertnotify=<cmd>", "Execute command when an alert is raised (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#endif
- argsman.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s, signet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex(), signetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnet4ChainParams->GetConsensus().defaultAssumeValid.GetHex(), signetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-fastprune", "Use smaller block files and lower minimum prune height for testing purposes", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
#if HAVE_SYSTEM
@@ -486,7 +488,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE_MB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY_HOURS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnet4ChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-par=<n>", strprintf("Set the number of script verification threads (0 = auto, up to %d, <0 = leave that many cores free, default: %d)",
MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -515,7 +517,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-addnode=<ip>", strprintf("Add a node to connect to and attempt to keep the connection open (see the addnode RPC help for more info). This option can be specified multiple times to add multiple nodes; connections are limited to %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
- argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
+ argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), testnet4BaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -542,7 +544,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
- argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
+ argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
#ifdef HAVE_SOCKADDR_UN
argsman.AddArg("-proxy=<ip:port|path>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled). May be a local file path prefixed with 'unix:' if the proxy supports it.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION, OptionsCategory::CONNECTION);
#else
@@ -659,7 +661,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpccookieperms=<readable-by>", strprintf("Set permissions on the RPC auth cookie file so that it is readable by [owner|group|all] (default: owner [via umask 0077])"), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
- argsman.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
+ argsman.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
argsman.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
argsman.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
@@ -906,6 +908,11 @@ bool AppInitParameterInteraction(const ArgsManager& args)
return InitError(errors);
}
+ // Testnet3 deprecation warning
+ if (chain == ChainType::TESTNET) {
+ LogInfo("Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4.\n");
+ }
+
// Warn if unrecognized section name are present in the config file.
bilingual_str warnings;
for (const auto& section : args.GetUnrecognizedSections()) {
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 0a5b7f9f0d..bbddc3dfec 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -100,6 +100,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
+ consensus.enforce_BIP94 = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
@@ -219,6 +220,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
+ consensus.enforce_BIP94 = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
@@ -297,6 +299,104 @@ public:
};
/**
+ * Testnet (v4): public test network which is reset from time to time.
+ */
+class CTestNet4Params : public CChainParams {
+public:
+ CTestNet4Params() {
+ m_chain_type = ChainType::TESTNET4;
+ consensus.signet_blocks = false;
+ consensus.signet_challenge.clear();
+ consensus.nSubsidyHalvingInterval = 210000;
+ consensus.BIP34Height = 1;
+ consensus.BIP34Hash = uint256{};
+ consensus.BIP65Height = 1;
+ consensus.BIP66Height = 1;
+ consensus.CSVHeight = 1;
+ consensus.SegwitHeight = 1;
+ consensus.MinBIP9WarningHeight = 0;
+ consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+ consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
+ consensus.nPowTargetSpacing = 10 * 60;
+ consensus.fPowAllowMinDifficultyBlocks = true;
+ consensus.enforce_BIP94 = true;
+ consensus.fPowNoRetargeting = false;
+ consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
+ consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay
+
+ // Deployment of Taproot (BIPs 340-342)
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
+
+ consensus.nMinimumChainWork = uint256{};
+ consensus.defaultAssumeValid = uint256{};
+
+ pchMessageStart[0] = 0x1c;
+ pchMessageStart[1] = 0x16;
+ pchMessageStart[2] = 0x3f;
+ pchMessageStart[3] = 0x28;
+ nDefaultPort = 48333;
+ nPruneAfterHeight = 1000;
+ m_assumed_blockchain_size = 0;
+ m_assumed_chain_state_size = 0;
+
+ const char* testnet4_genesis_msg = "03/May/2024 000000000000000000001ebd58c244970b3aa9d783bb001011fbe8ea8e98e00e";
+ const CScript testnet4_genesis_script = CScript() << ParseHex("000000000000000000000000000000000000000000000000000000000000000000") << OP_CHECKSIG;
+ genesis = CreateGenesisBlock(testnet4_genesis_msg,
+ testnet4_genesis_script,
+ 1714777860,
+ 393743547,
+ 0x1d00ffff,
+ 1,
+ 50 * COIN);
+ consensus.hashGenesisBlock = genesis.GetHash();
+ assert(consensus.hashGenesisBlock == uint256S("0x00000000da84f2bafbbc53dee25a72ae507ff4914b867c565be350b0da8bf043"));
+ assert(genesis.hashMerkleRoot == uint256S("0x7aa0a7ae1e223414cb807e40cd57e667b718e42aaf9306db9102fe28912b7b4e"));
+
+ vFixedSeeds.clear();
+ vSeeds.clear();
+ // nodes with support for servicebits filtering should be at the top
+ vSeeds.emplace_back("seed.testnet4.bitcoin.sprovoost.nl."); // Sjors Provoost
+ vSeeds.emplace_back("seed.testnet4.wiz.biz."); // Jason Maurice
+
+ base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
+ base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
+ base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
+ base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
+ base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};
+
+ bech32_hrp = "tb";
+
+ vFixedSeeds = std::vector<uint8_t>(std::begin(chainparams_seed_testnet4), std::end(chainparams_seed_testnet4));
+
+ fDefaultConsistencyChecks = false;
+ m_is_mockable_chain = false;
+
+ checkpointData = {
+ {
+ {},
+ }
+ };
+
+ m_assumeutxo_data = {
+ {}
+ };
+
+ chainTxData = ChainTxData{
+ .nTime = 0,
+ .tx_count = 0,
+ .dTxRate = 0,
+ };
+ }
+};
+
+/**
* Signet: test network with an additional consensus parameter (see BIP325).
*/
class SigNetParams : public CChainParams {
@@ -356,6 +456,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
+ consensus.enforce_BIP94 = false;
consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
@@ -434,6 +535,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
+ consensus.enforce_BIP94 = false;
consensus.fPowNoRetargeting = true;
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
@@ -563,6 +665,11 @@ std::unique_ptr<const CChainParams> CChainParams::TestNet()
return std::make_unique<const CTestNetParams>();
}
+std::unique_ptr<const CChainParams> CChainParams::TestNet4()
+{
+ return std::make_unique<const CTestNet4Params>();
+}
+
std::vector<int> CChainParams::GetAvailableSnapshotHeights() const
{
std::vector<int> heights;
diff --git a/src/kernel/chainparams.h b/src/kernel/chainparams.h
index e367de2f93..c4584600fd 100644
--- a/src/kernel/chainparams.h
+++ b/src/kernel/chainparams.h
@@ -161,6 +161,7 @@ public:
static std::unique_ptr<const CChainParams> SigNet(const SigNetOptions& options);
static std::unique_ptr<const CChainParams> Main();
static std::unique_ptr<const CChainParams> TestNet();
+ static std::unique_ptr<const CChainParams> TestNet4();
protected:
CChainParams() = default;
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index 0386689baf..30ffa302a4 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -50,6 +50,7 @@ static const int TOOLTIP_WRAP_THRESHOLD = 80;
#define QAPP_ORG_DOMAIN "bitcoin.org"
#define QAPP_APP_NAME_DEFAULT "Bitcoin-Qt"
#define QAPP_APP_NAME_TESTNET "Bitcoin-Qt-testnet"
+#define QAPP_APP_NAME_TESTNET4 "Bitcoin-Qt-testnet4"
#define QAPP_APP_NAME_SIGNET "Bitcoin-Qt-signet"
#define QAPP_APP_NAME_REGTEST "Bitcoin-Qt-regtest"
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 0e3a0d9a9d..baa19d7c24 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -115,6 +115,7 @@ static std::string DummyAddress(const CChainParams &params)
break;
case ChainType::SIGNET:
case ChainType::TESTNET:
+ case ChainType::TESTNET4:
addr = "tb1p35yvjel7srp783ztf8v6jdra7dhfzk5jaun8xz2qp6ws7z80n4tqa6qnlg";
break;
case ChainType::REGTEST:
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index b6314f5533..d3f7c02d05 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -19,6 +19,7 @@ static const struct {
} network_styles[] = {
{ChainType::MAIN, QAPP_APP_NAME_DEFAULT, 0, 0},
{ChainType::TESTNET, QAPP_APP_NAME_TESTNET, 70, 30},
+ {ChainType::TESTNET4, QAPP_APP_NAME_TESTNET4, 70, 30},
{ChainType::SIGNET, QAPP_APP_NAME_SIGNET, 35, 15},
{ChainType::REGTEST, QAPP_APP_NAME_REGTEST, 160, 30},
};
diff --git a/src/test/argsman_tests.cpp b/src/test/argsman_tests.cpp
index 5f0318e8c4..297595a9cf 100644
--- a/src/test/argsman_tests.cpp
+++ b/src/test/argsman_tests.cpp
@@ -644,10 +644,12 @@ BOOST_AUTO_TEST_CASE(util_GetChainTypeString)
{
TestArgsManager test_args;
const auto testnet = std::make_pair("-testnet", ArgsManager::ALLOW_ANY);
+ const auto testnet4 = std::make_pair("-testnet4", ArgsManager::ALLOW_ANY);
const auto regtest = std::make_pair("-regtest", ArgsManager::ALLOW_ANY);
- test_args.SetupArgs({testnet, regtest});
+ test_args.SetupArgs({testnet, testnet4, regtest});
const char* argv_testnet[] = {"cmd", "-testnet"};
+ const char* argv_testnet4[] = {"cmd", "-testnet4"};
const char* argv_regtest[] = {"cmd", "-regtest"};
const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
@@ -663,6 +665,12 @@ BOOST_AUTO_TEST_CASE(util_GetChainTypeString)
BOOST_CHECK(test_args.ParseParameters(2, argv_testnet, error));
BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
+ BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
+
+ BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+
BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "regtest");
@@ -758,8 +766,8 @@ struct ArgsMergeTestingSetup : public BasicTestingSetup {
ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
for (bool soft_set : {false, true}) {
for (bool force_set : {false, true}) {
- for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::SIGNET)}) {
- for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::SIGNET)}) {
+ for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
+ for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
for (bool net_specific : {false, true}) {
fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
}
@@ -913,7 +921,7 @@ BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
// Results file is formatted like:
//
// <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
- BOOST_CHECK_EQUAL(out_sha_hex, "d1e436c1cd510d0ec44d5205d4b4e3bee6387d316e0075c58206cb16603f3d82");
+ BOOST_CHECK_EQUAL(out_sha_hex, "f1ee5ab094cc43d16a6086fa7f2c10389e0f99902616b31bbf29189972ad1473");
}
// Similar test as above, but for ArgsManager::GetChainTypeString function.
@@ -1016,7 +1024,7 @@ BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
// Results file is formatted like:
//
// <input> || <output>
- BOOST_CHECK_EQUAL(out_sha_hex, "f263493e300023b6509963887444c41386f44b63bc30047eb8402e8c1144854c");
+ BOOST_CHECK_EQUAL(out_sha_hex, "9e60306e1363528bbc19a47f22bcede88e5d6815212f18ec8e6cdc4638dddab4");
}
BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 9aadebbe63..4af66af283 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -198,6 +198,11 @@ BOOST_AUTO_TEST_CASE(ChainParams_TESTNET_sanity)
sanity_check_chainparams(*m_node.args, ChainType::TESTNET);
}
+BOOST_AUTO_TEST_CASE(ChainParams_TESTNET4_sanity)
+{
+ sanity_check_chainparams(*m_node.args, ChainType::TESTNET4);
+}
+
BOOST_AUTO_TEST_CASE(ChainParams_SIGNET_sanity)
{
sanity_check_chainparams(*m_node.args, ChainType::SIGNET);
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index f462895edb..896840b0f3 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -419,7 +419,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
// check that any deployment on any chain can conceivably reach both
// ACTIVE and FAILED states in roughly the way we expect
- for (const auto& chain_type: {ChainType::MAIN, ChainType::TESTNET, ChainType::SIGNET, ChainType::REGTEST}) {
+ for (const auto& chain_type: {ChainType::MAIN, ChainType::TESTNET, ChainType::TESTNET4, ChainType::SIGNET, ChainType::REGTEST}) {
const auto chainParams = CreateChainParams(*m_node.args, chain_type);
uint32_t chain_all_vbits{0};
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
diff --git a/src/util/chaintype.cpp b/src/util/chaintype.cpp
index 8a199e352a..272466e7af 100644
--- a/src/util/chaintype.cpp
+++ b/src/util/chaintype.cpp
@@ -15,6 +15,8 @@ std::string ChainTypeToString(ChainType chain)
return "main";
case ChainType::TESTNET:
return "test";
+ case ChainType::TESTNET4:
+ return "testnet4";
case ChainType::SIGNET:
return "signet";
case ChainType::REGTEST:
@@ -29,6 +31,8 @@ std::optional<ChainType> ChainTypeFromString(std::string_view chain)
return ChainType::MAIN;
} else if (chain == "test") {
return ChainType::TESTNET;
+ } else if (chain == "testnet4") {
+ return ChainType::TESTNET4;
} else if (chain == "signet") {
return ChainType::SIGNET;
} else if (chain == "regtest") {
diff --git a/src/util/chaintype.h b/src/util/chaintype.h
index c73985df57..2fe734b64a 100644
--- a/src/util/chaintype.h
+++ b/src/util/chaintype.h
@@ -13,6 +13,7 @@ enum class ChainType {
TESTNET,
SIGNET,
REGTEST,
+ TESTNET4,
};
std::string ChainTypeToString(ChainType chain);
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index dc812d224f..bb20e2baa8 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -371,11 +371,44 @@ class ConfArgsTest(BitcoinTestFramework):
def test_acceptstalefeeestimates_arg_support(self):
self.log.info("Test -acceptstalefeeestimates option support")
conf_file = self.nodes[0].datadir_path / "bitcoin.conf"
- for chain, chain_name in {("main", ""), ("test", "testnet3"), ("signet", "signet")}:
+ for chain, chain_name in {("main", ""), ("test", "testnet3"), ("signet", "signet"), ("testnet4", "testnet4")}:
util.write_config(conf_file, n=0, chain=chain_name, extra_config='acceptstalefeeestimates=1\n')
self.nodes[0].assert_start_raises_init_error(expected_msg=f'Error: acceptstalefeeestimates is not supported on {chain} chain.')
util.write_config(conf_file, n=0, chain="regtest") # Reset to regtest
+ def test_testnet3_deprecation_msg(self):
+ self.log.info("Test testnet3 deprecation warning")
+ t3_warning_log = "Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4."
+
+ def warning_msg(node, approx_size):
+ return f'Warning: Disk space for "{node.datadir_path / node.chain / "blocks" }" may not accommodate the block files. Approximately {approx_size} GB of data will be stored in this directory.'
+
+ # Testnet3 node will log the warning
+ self.nodes[0].chain = 'testnet3'
+ self.nodes[0].replace_in_config([('regtest=', 'testnet='), ('[regtest]', '[test]')])
+ with self.nodes[0].assert_debug_log([t3_warning_log]):
+ self.start_node(0)
+ # Some CI environments will have limited space and some others won't
+ # so we need to handle both cases as a valid result.
+ self.nodes[0].stderr.seek(0)
+ err = self.nodes[0].stdout.read()
+ self.nodes[0].stderr.seek(0)
+ self.nodes[0].stderr.truncate()
+ if err != b'' and err != warning_msg(self.nodes[0], 42):
+ raise AssertionError("Unexpected stderr after shutdown of Testnet3 node")
+ self.stop_node(0)
+
+ # Testnet4 node will not log the warning
+ self.nodes[0].chain = 'testnet4'
+ self.nodes[0].replace_in_config([('testnet=', 'testnet4='), ('[test]', '[testnet4]')])
+ with self.nodes[0].assert_debug_log([], unexpected_msgs=[t3_warning_log]):
+ self.start_node(0)
+ self.stop_node(0)
+
+ # Reset to regtest
+ self.nodes[0].chain = 'regtest'
+ self.nodes[0].replace_in_config([('testnet4=', 'regtest='), ('[testnet4]', '[regtest]')])
+
def run_test(self):
self.test_log_buffer()
self.test_args_log()
@@ -389,6 +422,7 @@ class ConfArgsTest(BitcoinTestFramework):
self.test_ignored_conf()
self.test_ignored_default_conf()
self.test_acceptstalefeeestimates_arg_support()
+ self.test_testnet3_deprecation_msg()
# Remove the -datadir argument so it doesn't override the config file
self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")]
diff --git a/test/functional/wallet_crosschain.py b/test/functional/wallet_crosschain.py
index 3505d33e51..97db84c3e4 100755
--- a/test/functional/wallet_crosschain.py
+++ b/test/functional/wallet_crosschain.py
@@ -11,7 +11,7 @@ class WalletCrossChain(BitcoinTestFramework):
self.add_wallet_options(parser)
def set_test_params(self):
- self.num_nodes = 2
+ self.num_nodes = 3
self.setup_clean_chain = True
def skip_test_if_missing_module(self):
@@ -24,6 +24,12 @@ class WalletCrossChain(BitcoinTestFramework):
self.nodes[1].chain = 'testnet3'
self.nodes[1].extra_args = ['-maxconnections=0', '-prune=550'] # disable testnet sync
self.nodes[1].replace_in_config([('regtest=', 'testnet='), ('[regtest]', '[test]')])
+
+ # Switch node 2 to testnet4 before starting it.
+ self.nodes[2].chain = 'testnet4'
+ self.nodes[2].extra_args = ['-maxconnections=0', '-prune=550'] # disable testnet4 sync
+ self.nodes[2].replace_in_config([('regtest=', 'testnet4='), ('[regtest]', '[testnet4]')])
+
self.start_nodes()
def run_test(self):
@@ -39,19 +45,40 @@ class WalletCrossChain(BitcoinTestFramework):
self.nodes[1].createwallet(node1_wallet)
self.nodes[1].backupwallet(node1_wallet_backup)
self.nodes[1].unloadwallet(node1_wallet)
+ node2_wallet = self.nodes[2].datadir_path / 'node2_wallet'
+ node2_wallet_backup = self.nodes[0].datadir_path / 'node2_wallet.bak'
+ self.nodes[2].createwallet(node2_wallet)
+ self.nodes[2].backupwallet(node2_wallet_backup)
+ self.nodes[2].unloadwallet(node2_wallet)
self.log.info("Loading/restoring wallets into nodes with a different genesis block")
if self.options.descriptors:
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].loadwallet, node1_wallet)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].loadwallet, node2_wallet)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].loadwallet, node0_wallet)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].loadwallet, node0_wallet)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].loadwallet, node2_wallet)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].loadwallet, node1_wallet)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].restorewallet, 'w', node1_wallet_backup)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].restorewallet, 'w', node2_wallet_backup)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].restorewallet, 'w', node0_wallet_backup)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].restorewallet, 'w', node0_wallet_backup)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].restorewallet, 'w', node2_wallet_backup)
+ assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].restorewallet, 'w', node1_wallet_backup)
else:
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].loadwallet, node1_wallet)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].loadwallet, node2_wallet)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].loadwallet, node0_wallet)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].loadwallet, node0_wallet)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].loadwallet, node2_wallet)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].loadwallet, node1_wallet)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].restorewallet, 'w', node1_wallet_backup)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].restorewallet, 'w', node2_wallet_backup)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].restorewallet, 'w', node0_wallet_backup)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].restorewallet, 'w', node0_wallet_backup)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].restorewallet, 'w', node2_wallet_backup)
+ assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].restorewallet, 'w', node1_wallet_backup)
if not self.options.descriptors:
self.log.info("Override cross-chain wallet load protection")