Merge bitcoin/bitcoin#33473: [30.x] Backports & rc3

4e869a67aa doc: update example bitcoin conf for 30.0rc3 (fanquake)
a2ac6cce57 doc: update manual pages for v30.0rc3 (fanquake)
e4b568917c build: bump version to v30.0rc3 (fanquake)
f957c2171d contrib: fix using macdploy script without translations. (amisha)
1eb578045d depends: static libxcb_cursor (fanquake)
e4f9ec2f05 test: add more TRUC reorg coverge (Greg Sanders)
3485252584 Mempool: Do not enforce TRUC checks on reorg (Greg Sanders)
a3a1dcb589 fuzz: don't bypass_limits for most mempool harnesses (Greg Sanders)
fce1c60770 datacarrier: Undeprecate configuration option (Anthony Towns)
b75afaccb8 doc: rpc: fix case typo in `finalizepsbt` help (final_scriptwitness) (Sebastian Falbesoner)
45703931e5 miner: fix `addPackageTxs` unsigned integer overflow (ismaelsadeeq)
1e348bc55a rpc: fix getblock(header) returns target for tip (Sjors Provoost)
4ec30d53ec test: add block 2016 to mock mainnet (Sjors Provoost)

Pull request description:

  Backports:
  * #33434
  * #33446
  * #33453
  * #33475
  * #33482
  * #33484
  * #33504

  Includes changes for `v30.0rc3`:
  * Version bump
  * Regen manpages
  * Regen exmaple .conf

ACKs for top commit:
  marcofleon:
    lgtm ACK 4e869a67aa
  dergoegge:
    ACK 4e869a67aa
  hebasto:
    ACK 4e869a67aa, I agree on the backported PRs. I've reproduced locally all backports, the manpages update, and the example `bitcoin.conf` updated, and obtained zero diff with this PR.
  Zero-1729:
    LGTM ACK 4e869a67aa

Tree-SHA512: 90bffbb6dfe2b512167b5e08253ea163b714505ec3ef2247d798c40b30713a7db13cf0b5486b5f9e0e5b3ba53108dfaeea47276c40816eeb81065d42bd402379
This commit is contained in:
merge-script 2025-10-06 10:37:26 +01:00
commit d5e0077bef
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1
26 changed files with 145 additions and 118 deletions

View File

@ -30,7 +30,7 @@ set(CLIENT_NAME "Bitcoin Core")
set(CLIENT_VERSION_MAJOR 30) set(CLIENT_VERSION_MAJOR 30)
set(CLIENT_VERSION_MINOR 0) set(CLIENT_VERSION_MINOR 0)
set(CLIENT_VERSION_BUILD 0) set(CLIENT_VERSION_BUILD 0)
set(CLIENT_VERSION_RC 2) set(CLIENT_VERSION_RC 3)
set(CLIENT_VERSION_IS_RELEASE "true") set(CLIENT_VERSION_IS_RELEASE "true")
set(COPYRIGHT_YEAR "2025") set(COPYRIGHT_YEAR "2025")

View File

@ -112,7 +112,6 @@ ELF_ALLOWED_LIBRARIES = {
'libfontconfig.so.1', # font support 'libfontconfig.so.1', # font support
'libfreetype.so.6', # font parsing 'libfreetype.so.6', # font parsing
'libdl.so.2', # programming interface to dynamic linker 'libdl.so.2', # programming interface to dynamic linker
'libxcb-cursor.so.0',
'libxcb-icccm.so.4', 'libxcb-icccm.so.4',
'libxcb-image.so.0', 'libxcb-image.so.0',
'libxcb-shm.so.0', 'libxcb-shm.so.0',

View File

@ -6,7 +6,7 @@ $(package)_sha256_hash=0e9c5446dc6f3beb8af6ebfcc9e27bcc6da6fe2860f7fc07b99144dfa
$(package)_dependencies=libxcb libxcb_util_render libxcb_util_image $(package)_dependencies=libxcb libxcb_util_render libxcb_util_image
define $(package)_set_vars define $(package)_set_vars
$(package)_config_opts = --disable-static $(package)_config_opts = --disable-shared
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts += --disable-dependency-tracking --enable-option-checking
endef endef

View File

@ -81,8 +81,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
sudo apt-get install qt6-base-dev qt6-tools-dev qt6-l10n-tools qt6-tools-dev-tools libgl-dev sudo apt-get install qt6-base-dev qt6-tools-dev qt6-l10n-tools qt6-tools-dev-tools libgl-dev
For Qt 6.5 and later, the `libxcb-cursor0` package must be installed at runtime.
Additionally, to support Wayland protocol for modern desktop environments: Additionally, to support Wayland protocol for modern desktop environments:
sudo apt install qt6-wayland sudo apt install qt6-wayland
@ -133,8 +131,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
sudo dnf install qt6-qtbase-devel qt6-qttools-devel sudo dnf install qt6-qtbase-devel qt6-qttools-devel
For Qt 6.5 and later, the `xcb-util-cursor` package must be installed at runtime.
Additionally, to support Wayland protocol for modern desktop environments: Additionally, to support Wayland protocol for modern desktop environments:
sudo dnf install qt6-qtwayland sudo dnf install qt6-qtwayland
@ -182,8 +178,6 @@ the necessary parts of Qt, the libqrencode and pass `-DBUILD_GUI=ON`. Skip if yo
apk add qt6-qtbase-dev qt6-qttools-dev apk add qt6-qtbase-dev qt6-qttools-dev
For Qt 6.5 and later, the `xcb-util-cursor` package must be installed at runtime.
The GUI will be able to encode addresses in QR codes unless this feature is explicitly disabled. To install libqrencode, run: The GUI will be able to encode addresses in QR codes unless this feature is explicitly disabled. To install libqrencode, run:
apk add libqrencode-dev apk add libqrencode-dev

View File

@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-CLI "1" "September 2025" "bitcoin-cli v30.0.0rc2" "User Commands" .TH BITCOIN-CLI "1" "October 2025" "bitcoin-cli v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin-cli \- manual page for bitcoin-cli v30.0.0rc2 bitcoin-cli \- manual page for bitcoin-cli v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin-cli .B bitcoin-cli
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] [\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR]
@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v30.0.0rc2
.B bitcoin-cli .B bitcoin-cli
[\fI\,options\/\fR] \fI\,help <command>\/\fR [\fI\,options\/\fR] \fI\,help <command>\/\fR
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core RPC client version v30.0.0rc2 Bitcoin Core RPC client version v30.0.0rc3
.PP .PP
The bitcoin\-cli utility provides a command line interface to interact with a Bitcoin Core RPC server. The bitcoin\-cli utility provides a command line interface to interact with a Bitcoin Core RPC server.
.PP .PP

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-QT "1" "September 2025" "bitcoin-qt v30.0.0rc2" "User Commands" .TH BITCOIN-QT "1" "October 2025" "bitcoin-qt v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin-qt \- manual page for bitcoin-qt v30.0.0rc2 bitcoin-qt \- manual page for bitcoin-qt v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin-qt .B bitcoin-qt
[\fI\,options\/\fR] [\fI\,URI\/\fR] [\fI\,options\/\fR] [\fI\,URI\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core version v30.0.0rc2 Bitcoin Core version v30.0.0rc3
.PP .PP
The bitcoin\-qt application provides a graphical interface for interacting with Bitcoin Core. The bitcoin\-qt application provides a graphical interface for interacting with Bitcoin Core.
.PP .PP
@ -695,13 +695,13 @@ Equivalent bytes per sigop in transactions for relay and mining
.HP .HP
\fB\-datacarrier\fR \fB\-datacarrier\fR
.IP .IP
(DEPRECATED) Relay and mine data carrier transactions (default: 1) Relay and mine data carrier transactions (default: 1)
.HP .HP
\fB\-datacarriersize\fR \fB\-datacarriersize\fR
.IP .IP
(DEPRECATED) Relay and mine transactions whose data\-carrying raw Relay and mine transactions whose data\-carrying raw scriptPubKeys in
scriptPubKeys in aggregate are of this size or less, allowing aggregate are of this size or less, allowing multiple outputs
multiple outputs (default: 100000) (default: 100000)
.HP .HP
\fB\-minrelaytxfee=\fR<amt> \fB\-minrelaytxfee=\fR<amt>
.IP .IP

View File

@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-TX "1" "September 2025" "bitcoin-tx v30.0.0rc2" "User Commands" .TH BITCOIN-TX "1" "October 2025" "bitcoin-tx v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin-tx \- manual page for bitcoin-tx v30.0.0rc2 bitcoin-tx \- manual page for bitcoin-tx v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin-tx .B bitcoin-tx
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] [\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR]
@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v30.0.0rc2
.B bitcoin-tx .B bitcoin-tx
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] [\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core bitcoin\-tx utility version v30.0.0rc2 Bitcoin Core bitcoin\-tx utility version v30.0.0rc3
.PP .PP
The bitcoin\-tx tool is used for creating and modifying bitcoin transactions. The bitcoin\-tx tool is used for creating and modifying bitcoin transactions.
.PP .PP

View File

@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-UTIL "1" "September 2025" "bitcoin-util v30.0.0rc2" "User Commands" .TH BITCOIN-UTIL "1" "October 2025" "bitcoin-util v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin-util \- manual page for bitcoin-util v30.0.0rc2 bitcoin-util \- manual page for bitcoin-util v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin-util .B bitcoin-util
[\fI\,options\/\fR] [\fI\,command\/\fR] [\fI\,options\/\fR] [\fI\,command\/\fR]
@ -9,7 +9,7 @@ bitcoin-util \- manual page for bitcoin-util v30.0.0rc2
.B bitcoin-util .B bitcoin-util
[\fI\,options\/\fR] \fI\,grind <hex-block-header>\/\fR [\fI\,options\/\fR] \fI\,grind <hex-block-header>\/\fR
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core bitcoin\-util utility version v30.0.0rc2 Bitcoin Core bitcoin\-util utility version v30.0.0rc3
.PP .PP
The bitcoin\-util tool provides bitcoin related functionality that does not rely on the ability to access a running node. Available [commands] are listed below. The bitcoin\-util tool provides bitcoin related functionality that does not rely on the ability to access a running node. Available [commands] are listed below.
.SH OPTIONS .SH OPTIONS

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN-WALLET "1" "September 2025" "bitcoin-wallet v30.0.0rc2" "User Commands" .TH BITCOIN-WALLET "1" "October 2025" "bitcoin-wallet v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin-wallet \- manual page for bitcoin-wallet v30.0.0rc2 bitcoin-wallet \- manual page for bitcoin-wallet v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin-wallet .B bitcoin-wallet
[\fI\,options\/\fR] \fI\,<command>\/\fR [\fI\,options\/\fR] \fI\,<command>\/\fR
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core bitcoin\-wallet utility version v30.0.0rc2 Bitcoin Core bitcoin\-wallet utility version v30.0.0rc3
.PP .PP
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files. bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
.PP .PP

View File

@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIN "1" "September 2025" "bitcoin v30.0.0rc2" "User Commands" .TH BITCOIN "1" "October 2025" "bitcoin v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoin \- manual page for bitcoin v30.0.0rc2 bitcoin \- manual page for bitcoin v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoin .B bitcoin
[\fI\,OPTIONS\/\fR] \fI\,COMMAND\/\fR... [\fI\,OPTIONS\/\fR] \fI\,COMMAND\/\fR...

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH BITCOIND "1" "September 2025" "bitcoind v30.0.0rc2" "User Commands" .TH BITCOIND "1" "October 2025" "bitcoind v30.0.0rc3" "User Commands"
.SH NAME .SH NAME
bitcoind \- manual page for bitcoind v30.0.0rc2 bitcoind \- manual page for bitcoind v30.0.0rc3
.SH SYNOPSIS .SH SYNOPSIS
.B bitcoind .B bitcoind
[\fI\,options\/\fR] [\fI\,options\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Bitcoin Core daemon version v30.0.0rc2 Bitcoin Core daemon version v30.0.0rc3
.PP .PP
The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses. The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses.
.PP .PP
@ -695,13 +695,13 @@ Equivalent bytes per sigop in transactions for relay and mining
.HP .HP
\fB\-datacarrier\fR \fB\-datacarrier\fR
.IP .IP
(DEPRECATED) Relay and mine data carrier transactions (default: 1) Relay and mine data carrier transactions (default: 1)
.HP .HP
\fB\-datacarriersize\fR \fB\-datacarriersize\fR
.IP .IP
(DEPRECATED) Relay and mine transactions whose data\-carrying raw Relay and mine transactions whose data\-carrying raw scriptPubKeys in
scriptPubKeys in aggregate are of this size or less, allowing aggregate are of this size or less, allowing multiple outputs
multiple outputs (default: 100000) (default: 100000)
.HP .HP
\fB\-minrelaytxfee=\fR<amt> \fB\-minrelaytxfee=\fR<amt>
.IP .IP

View File

@ -576,12 +576,12 @@
# (default: 20) # (default: 20)
#bytespersigop=1 #bytespersigop=1
# (DEPRECATED) Relay and mine data carrier transactions (default: 1) # Relay and mine data carrier transactions (default: 1)
#datacarrier=1 #datacarrier=1
# (DEPRECATED) Relay and mine transactions whose data-carrying raw # Relay and mine transactions whose data-carrying raw scriptPubKeys in
# scriptPubKeys in aggregate are of this size or less, allowing # aggregate are of this size or less, allowing multiple outputs
# multiple outputs (default: 100000) # (default: 100000)
#datacarriersize=1 #datacarriersize=1
# Fees (in BTC/kvB) smaller than this are considered zero fee for # Fees (in BTC/kvB) smaller than this are considered zero fee for

View File

@ -658,9 +658,9 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarrier", strprintf("(DEPRECATED) Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarriersize", argsman.AddArg("-datacarriersize",
strprintf("(DEPRECATED) Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate " strprintf("Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate "
"are of this size or less, allowing multiple outputs (default: %u)", "are of this size or less, allowing multiple outputs (default: %u)",
MAX_OP_RETURN_RELAY), MAX_OP_RETURN_RELAY),
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
@ -903,10 +903,6 @@ bool AppInitParameterInteraction(const ArgsManager& args)
InitWarning(_("Option '-checkpoints' is set but checkpoints were removed. This option has no effect.")); InitWarning(_("Option '-checkpoints' is set but checkpoints were removed. This option has no effect."));
} }
if (args.IsArgSet("-datacarriersize") || args.IsArgSet("-datacarrier")) {
InitWarning(_("Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated and are expected to be removed in a future version."));
}
// We no longer limit the orphanage based on number of transactions but keep the option to warn users who still have it in their config. // We no longer limit the orphanage based on number of transactions but keep the option to warn users who still have it in their config.
if (args.IsArgSet("-maxorphantx")) { if (args.IsArgSet("-maxorphantx")) {
InitWarning(_("Option '-maxorphantx' is set but no longer has any effect (see release notes). Please remove it from your configuration.")); InitWarning(_("Option '-maxorphantx' is set but no longer has any effect (see release notes). Please remove it from your configuration."));

View File

@ -397,8 +397,8 @@ void BlockAssembler::addPackageTxs(int& nPackagesSelected, int& nDescendantsUpda
++nConsecutiveFailed; ++nConsecutiveFailed;
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight > if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight +
m_options.nBlockMaxWeight - BLOCK_FULL_ENOUGH_WEIGHT_DELTA) { BLOCK_FULL_ENOUGH_WEIGHT_DELTA > m_options.nBlockMaxWeight) {
// Give up if we're close to full and haven't succeeded in a while // Give up if we're close to full and haven't succeeded in a while
break; break;
} }

View File

@ -166,7 +166,7 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
result.pushKV("mediantime", blockindex.GetMedianTimePast()); result.pushKV("mediantime", blockindex.GetMedianTimePast());
result.pushKV("nonce", blockindex.nNonce); result.pushKV("nonce", blockindex.nNonce);
result.pushKV("bits", strprintf("%08x", blockindex.nBits)); result.pushKV("bits", strprintf("%08x", blockindex.nBits));
result.pushKV("target", GetTarget(tip, pow_limit).GetHex()); result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
result.pushKV("difficulty", GetDifficulty(blockindex)); result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex.nChainWork.GetHex()); result.pushKV("chainwork", blockindex.nChainWork.GetHex());
result.pushKV("nTx", blockindex.nTx); result.pushKV("nTx", blockindex.nTx);

View File

@ -1608,7 +1608,7 @@ static RPCHelpMan finalizepsbt()
return RPCHelpMan{"finalizepsbt", return RPCHelpMan{"finalizepsbt",
"Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n" "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n"
"network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n" "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n"
"created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n" "created which has the final_scriptSig and final_scriptwitness fields filled for inputs that are complete.\n"
"Implements the Finalizer and Extractor roles.\n", "Implements the Finalizer and Extractor roles.\n",
{ {
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}, {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"},

View File

@ -325,7 +325,7 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool)
return ProcessNewPackage(chainstate, tx_pool, txs, /*test_accept=*/single_submit, /*client_maxfeerate=*/{})); return ProcessNewPackage(chainstate, tx_pool, txs, /*test_accept=*/single_submit, /*client_maxfeerate=*/{}));
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, txs.back(), GetTime(), const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, txs.back(), GetTime(),
/*bypass_limits=*/fuzzed_data_provider.ConsumeBool(), /*test_accept=*/!single_submit)); /*bypass_limits=*/false, /*test_accept=*/!single_submit));
if (!single_submit && result_package.m_state.GetResult() != PackageValidationResult::PCKG_POLICY) { if (!single_submit && result_package.m_state.GetResult() != PackageValidationResult::PCKG_POLICY) {
// We don't know anything about the validity since transactions were randomly generated, so // We don't know anything about the validity since transactions were randomly generated, so

View File

@ -296,7 +296,6 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
std::set<CTransactionRef> added; std::set<CTransactionRef> added;
auto txr = std::make_shared<TransactionsDelta>(removed, added); auto txr = std::make_shared<TransactionsDelta>(removed, added);
node.validation_signals->RegisterSharedValidationInterface(txr); node.validation_signals->RegisterSharedValidationInterface(txr);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
// Make sure ProcessNewPackage on one transaction works. // Make sure ProcessNewPackage on one transaction works.
// The result is not guaranteed to be the same as what is returned by ATMP. // The result is not guaranteed to be the same as what is returned by ATMP.
@ -311,7 +310,7 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
it->second.m_result_type == MempoolAcceptResult::ResultType::INVALID); it->second.m_result_type == MempoolAcceptResult::ResultType::INVALID);
} }
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false)); const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), /*bypass_limits=*/false, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID; const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
node.validation_signals->SyncWithValidationInterfaceQueue(); node.validation_signals->SyncWithValidationInterfaceQueue();
node.validation_signals->UnregisterSharedValidationInterface(txr); node.validation_signals->UnregisterSharedValidationInterface(txr);
@ -394,6 +393,9 @@ FUZZ_TARGET(tx_pool, .init = initialize_tx_pool)
chainstate.SetMempool(&tx_pool); chainstate.SetMempool(&tx_pool);
// If we ever bypass limits, do not do TRUC invariants checks
bool ever_bypassed_limits{false};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300) LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
{ {
const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids); const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids);
@ -412,15 +414,19 @@ FUZZ_TARGET(tx_pool, .init = initialize_tx_pool)
tx_pool.PrioritiseTransaction(txid, delta); tx_pool.PrioritiseTransaction(txid, delta);
} }
const bool bypass_limits{fuzzed_data_provider.ConsumeBool()};
ever_bypassed_limits |= bypass_limits;
const auto tx = MakeTransactionRef(mut_tx); const auto tx = MakeTransactionRef(mut_tx);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false)); const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID; const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
if (accepted) { if (accepted) {
txids.push_back(tx->GetHash()); txids.push_back(tx->GetHash());
if (!ever_bypassed_limits) {
CheckMempoolTRUCInvariants(tx_pool); CheckMempoolTRUCInvariants(tx_pool);
} }
} }
}
Finish(fuzzed_data_provider, tx_pool, chainstate); Finish(fuzzed_data_provider, tx_pool, chainstate);
} }
} // namespace } // namespace

View File

@ -1044,6 +1044,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Even though just checking direct mempool parents for inheritance would be sufficient, we // Even though just checking direct mempool parents for inheritance would be sufficient, we
// check using the full ancestor set here because it's more convenient to use what we have // check using the full ancestor set here because it's more convenient to use what we have
// already calculated. // already calculated.
if (!args.m_bypass_limits) {
if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) { if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
// Single transaction contexts only. // Single transaction contexts only.
if (args.m_allow_sibling_eviction && err->second != nullptr) { if (args.m_allow_sibling_eviction && err->second != nullptr) {
@ -1066,6 +1067,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first); return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
} }
} }
}
// A transaction that spends outputs that would be replaced by it is invalid. Now // A transaction that spends outputs that would be replaced by it is invalid. Now
// that we have the set of all ancestors we can detect this // that we have the set of all ancestors we can detect this

View File

@ -11,9 +11,10 @@ The alternate mainnet chain was generated as follows:
- restart node with a faketime 2 minutes later - restart node with a faketime 2 minutes later
```sh ```sh
for i in {1..2015} for i in {1..2016}
do do
faketime "`date -d @"$(( 1231006505 + $i * 120 ))" +'%Y-%m-%d %H:%M:%S'`" \ t=$(( 1231006505 + $i * 120 ))
faketime "`date -d @$t +'%Y-%m-%d %H:%M:%S'`" \
bitcoind -connect=0 -nocheckpoints -stopatheight=$i bitcoind -connect=0 -nocheckpoints -stopatheight=$i
done done
``` ```
@ -21,7 +22,9 @@ done
The CPU miner is kept running as follows: The CPU miner is kept running as follows:
```sh ```sh
./minerd --coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r --no-stratum --algo sha256d --no-longpoll --scantime 3 --retry-pause 1 ./minerd -u ... -p ... -o http://127.0.0.1:8332 --no-stratum \
--coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r \
--algo sha256d --no-longpoll --scantime 3 --retry-pause 1
``` ```
The payout address is derived from first BIP32 test vector master key: The payout address is derived from first BIP32 test vector master key:
@ -40,3 +43,8 @@ The timestamp was not kept constant because at difficulty 1 it's not sufficient
to only grind the nonce. Grinding the extra_nonce or version field instead to only grind the nonce. Grinding the extra_nonce or version field instead
would have required additional (stratum) software. It would also make it more would have required additional (stratum) software. It would also make it more
complicated to reconstruct the blocks in this test. complicated to reconstruct the blocks in this test.
The `getblocktemplate` RPC code needs to be patched to ignore not being connected
to any peers, and to ignore the IBD status check.
On macOS use `faketime "@$t"` instead.

View File

@ -2014,7 +2014,8 @@
1231247971, 1231247971,
1231248071, 1231248071,
1231248198, 1231248198,
1231248322 1231248322,
1231248621
], ],
"nonces": [ "nonces": [
2345621585, 2345621585,
@ -4031,6 +4032,7 @@
3658502865, 3658502865,
2519048297, 2519048297,
1915965760, 1915965760,
1183846025 1183846025,
2713372123
] ]
} }

View File

@ -100,17 +100,5 @@ class DataCarrierTest(BitcoinTestFramework):
self.test_null_data_transaction(node=self.nodes[2], data=one_byte, success=True) self.test_null_data_transaction(node=self.nodes[2], data=one_byte, success=True)
self.test_null_data_transaction(node=self.nodes[3], data=one_byte, success=False) self.test_null_data_transaction(node=self.nodes[3], data=one_byte, success=False)
# Clean shutdown boilerplate due to deprecation
self.expected_stderr = [
"", # node 0 has no deprecated options
"Warning: Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated and are expected to be removed in a future version.",
"Warning: Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated and are expected to be removed in a future version.",
"Warning: Options '-datacarrier' or '-datacarriersize' are set but are marked as deprecated and are expected to be removed in a future version.",
]
for i in range(self.num_nodes):
self.stop_node(i, expected_stderr=self.expected_stderr[i])
if __name__ == '__main__': if __name__ == '__main__':
DataCarrierTest(__file__).main() DataCarrierTest(__file__).main()

View File

@ -165,23 +165,36 @@ class MempoolTRUC(BitcoinTestFramework):
def test_truc_reorg(self): def test_truc_reorg(self):
node = self.nodes[0] node = self.nodes[0]
self.log.info("Test that, during a reorg, TRUC rules are not enforced") self.log.info("Test that, during a reorg, TRUC rules are not enforced")
tx_v2_block = self.wallet.send_self_transfer(from_node=node, version=2) self.check_mempool([])
tx_v3_block = self.wallet.send_self_transfer(from_node=node, version=3)
tx_v3_block2 = self.wallet.send_self_transfer(from_node=node, version=3) # Testing 2<-3 versions allowed
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"]]) tx_v2_block = self.wallet.create_self_transfer(version=2)
# Testing 3<-2 versions allowed
tx_v3_block = self.wallet.create_self_transfer(version=3)
# Testing overly-large child size
tx_v3_block2 = self.wallet.create_self_transfer(version=3)
# Also create a linear chain of 3 TRUC transactions that will be directly mined, followed by one v2 in-mempool after block is made
tx_chain_1 = self.wallet.create_self_transfer(version=3)
tx_chain_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_1["new_utxo"], version=3)
tx_chain_3 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_2["new_utxo"], version=3)
tx_to_mine = [tx_v3_block["hex"], tx_v2_block["hex"], tx_v3_block2["hex"], tx_chain_1["hex"], tx_chain_2["hex"], tx_chain_3["hex"]]
block = self.generateblock(node, output="raw(42)", transactions=tx_to_mine)
block = self.generate(node, 1)
self.check_mempool([]) self.check_mempool([])
tx_v2_from_v3 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block["new_utxo"], version=2) tx_v2_from_v3 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block["new_utxo"], version=2)
tx_v3_from_v2 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v2_block["new_utxo"], version=3) tx_v3_from_v2 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v2_block["new_utxo"], version=3)
tx_v3_child_large = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block2["new_utxo"], target_vsize=1250, version=3) tx_v3_child_large = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block2["new_utxo"], target_vsize=1250, version=3)
assert_greater_than(node.getmempoolentry(tx_v3_child_large["txid"])["vsize"], TRUC_CHILD_MAX_VSIZE) assert_greater_than(node.getmempoolentry(tx_v3_child_large["txid"])["vsize"], TRUC_CHILD_MAX_VSIZE)
self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"]]) tx_chain_4 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_chain_3["new_utxo"], version=2)
node.invalidateblock(block[0]) self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_4["txid"]])
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"], tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"]])
# This is needed because generate() will create the exact same block again.
node.reconsiderblock(block[0])
# Reorg should have all block transactions re-accepted, ignoring TRUC enforcement
node.invalidateblock(block["hash"])
self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"], tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_1["txid"], tx_chain_2["txid"], tx_chain_3["txid"], tx_chain_4["txid"]])
@cleanup(extra_args=["-limitdescendantsize=10"]) @cleanup(extra_args=["-limitdescendantsize=10"])
def test_nondefault_package_limits(self): def test_nondefault_package_limits(self):

View File

@ -53,15 +53,15 @@ class MiningMainnetTest(BitcoinTestFramework):
help='Block data file (default: %(default)s)', help='Block data file (default: %(default)s)',
) )
def mine(self, height, prev_hash, blocks, node, fees=0): def mine(self, height, prev_hash, blocks, node):
self.log.debug(f"height={height}") self.log.debug(f"height={height}")
block = CBlock() block = CBlock()
block.nVersion = 0x20000000 block.nVersion = 0x20000000
block.hashPrevBlock = int(prev_hash, 16) block.hashPrevBlock = int(prev_hash, 16)
block.nTime = blocks['timestamps'][height - 1] block.nTime = blocks['timestamps'][height - 1]
block.nBits = DIFF_1_N_BITS block.nBits = DIFF_1_N_BITS if height < 2016 else DIFF_4_N_BITS
block.nNonce = blocks['nonces'][height - 1] block.nNonce = blocks['nonces'][height - 1]
block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), retarget_period=2016)] block.vtx = [create_coinbase(height=height, script_pubkey=bytes.fromhex(COINBASE_SCRIPT_PUBKEY), halving_period=210000)]
# The alternate mainnet chain was mined with non-timelocked coinbase txs. # The alternate mainnet chain was mined with non-timelocked coinbase txs.
block.vtx[0].nLockTime = 0 block.vtx[0].nLockTime = 0
block.vtx[0].vin[0].nSequence = SEQUENCE_FINAL block.vtx[0].vin[0].nSequence = SEQUENCE_FINAL
@ -82,10 +82,13 @@ class MiningMainnetTest(BitcoinTestFramework):
self.log.info("Load alternative mainnet blocks") self.log.info("Load alternative mainnet blocks")
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile) path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
prev_hash = node.getbestblockhash() prev_hash = node.getbestblockhash()
blocks = None
with open(path, encoding='utf-8') as f: with open(path, encoding='utf-8') as f:
blocks = json.load(f) blocks = json.load(f)
n_blocks = len(blocks['timestamps']) n_blocks = len(blocks['timestamps'])
assert_equal(n_blocks, 2015) assert_equal(n_blocks, 2016)
# Mine up to the last block of the first retarget period
for i in range(2015): for i in range(2015):
prev_hash = self.mine(i + 1, prev_hash, blocks, node) prev_hash = self.mine(i + 1, prev_hash, blocks, node)
@ -102,5 +105,21 @@ class MiningMainnetTest(BitcoinTestFramework):
assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS)) assert_equal(mining_info['next']['bits'], nbits_str(DIFF_4_N_BITS))
assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET)) assert_equal(mining_info['next']['target'], target_str(DIFF_4_TARGET))
# Mine first block of the second retarget period
height = 2016
prev_hash = self.mine(height, prev_hash, blocks, node)
assert_equal(node.getblockcount(), height)
mining_info = node.getmininginfo()
assert_equal(mining_info['difficulty'], 4)
self.log.info("getblock RPC should show historical target")
block_info = node.getblock(node.getblockhash(1))
assert_equal(block_info['difficulty'], 1)
assert_equal(block_info['bits'], nbits_str(DIFF_1_N_BITS))
assert_equal(block_info['target'], target_str(DIFF_1_TARGET))
if __name__ == '__main__': if __name__ == '__main__':
MiningMainnetTest(__file__).main() MiningMainnetTest(__file__).main()

View File

@ -144,7 +144,7 @@ def script_BIP34_coinbase_height(height):
return CScript([CScriptNum(height)]) return CScript([CScriptNum(height)])
def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, retarget_period=REGTEST_RETARGET_PERIOD): def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_script=None, fees=0, nValue=50, halving_period=REGTEST_RETARGET_PERIOD):
"""Create a coinbase transaction. """Create a coinbase transaction.
If pubkey is passed in, the coinbase output will be a P2PK output; If pubkey is passed in, the coinbase output will be a P2PK output;
@ -158,7 +158,7 @@ def create_coinbase(height, pubkey=None, *, script_pubkey=None, extra_output_scr
coinbaseoutput = CTxOut() coinbaseoutput = CTxOut()
coinbaseoutput.nValue = nValue * COIN coinbaseoutput.nValue = nValue * COIN
if nValue == 50: if nValue == 50:
halvings = int(height / retarget_period) halvings = int(height / halving_period)
coinbaseoutput.nValue >>= halvings coinbaseoutput.nValue >>= halvings
coinbaseoutput.nValue += fees coinbaseoutput.nValue += fees
if pubkey is not None: if pubkey is not None: