testnet: Introduce Testnet4

This commit is contained in:
Fabian Jahr 2024-03-31 23:50:42 +02:00
parent 902dd14382
commit 74a04f9e7a
No known key found for this signature in database
GPG Key ID: F13D1E9D890798CD
26 changed files with 258 additions and 30 deletions

View File

@ -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

View File

@ -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__':

View File

@ -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
-------------------------------------

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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();

View File

@ -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);

View File

@ -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:

View File

@ -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

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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()) {

View File

@ -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
@ -296,6 +298,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).
*/
@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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:

View File

@ -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},
};

View File

@ -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)

View File

@ -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);

View File

@ -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) {

View File

@ -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") {

View File

@ -13,6 +13,7 @@ enum class ChainType {
TESTNET,
SIGNET,
REGTEST,
TESTNET4,
};
std::string ChainTypeToString(ChainType chain);

View File

@ -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")]

View File

@ -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")