diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md
index 2eb6846747a..388ddd5453e 100644
--- a/contrib/seeds/README.md
+++ b/contrib/seeds/README.md
@@ -15,8 +15,7 @@ DNS seed, virtu's crawler, and asmap community AS map data. Run the following co
from the `/contrib/seeds` directory:
```
-curl https://bitcoin.sipa.be/seeds.txt.gz | gzip -dc > seeds_main.txt
-curl https://21.ninja/seeds.txt.gz | gzip -dc >> seeds_main.txt
+curl https://21.ninja/seeds.txt.gz | gzip -dc > seeds_main.txt
curl https://mainnet.achownodes.xyz/seeds.txt.gz | gzip -dc >> seeds_main.txt
curl https://signet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_signet.txt
curl https://testnet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_test.txt
diff --git a/doc/bips.md b/doc/bips.md
index c814717a09f..1dd84c1a746 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -49,6 +49,7 @@ BIPs that are implemented by Bitcoin Core:
* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)).
* [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)).
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
+* [`BIP 323`](https://github.com/bitcoin/bips/blob/master/bip-0323.mediawiki): BIP 9 bits 5 to 28 (inclusive) are ignored for soft-fork signalling and unknown soft fork warnings as of **v30.4**.
* [`BIP 324`](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki): The v2 transport protocol specified by BIP324 and the associated `NODE_P2P_V2` service bit are supported as of **v26.0**, but off by default ([PR 28331](https://github.com/bitcoin/bitcoin/pull/28331)). On by default as of **v27.0** ([PR 29347](https://github.com/bitcoin/bitcoin/pull/29347)).
* [`BIP 325`](https://github.com/bitcoin/bips/blob/master/bip-0325.mediawiki): Signet test network is supported as of **v0.21.0** ([PR 18267](https://github.com/bitcoin/bitcoin/pull/18267)).
* [`BIP 339`](https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki): Relay of transactions by wtxid is supported as of **v0.21.0** ([PR 18044](https://github.com/bitcoin/bitcoin/pull/18044)).
diff --git a/doc/release-notes.md b/doc/release-notes.md
index f8ccd6615c1..854c7e44a5a 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,11 +1,11 @@
-v30.3 Release Notes
+v30.x Release Notes
===================
-Bitcoin Core version v30.3 is now available from:
+Bitcoin Core version v30.x is now available from:
-
+
-This release includes new features, various bug fixes and performance
+This release includes various bug fixes and performance
improvements, as well as updated translations.
Please report bugs using the issue tracker at GitHub:
@@ -40,128 +40,33 @@ unsupported systems.
Notable changes
===============
-This release fixes an issue where the chainstate database would repeatedly
-rewrite large portions of itself, causing excessive disk reads and writes
-during normal operation.
+- BIP 9 bits 5 to 28 inclusive are now ignored for soft fork signaling, as per
+ BIP 323. We won't warn about unknown deployments when receiving blocks that
+ set any of those bits in their version. (#34779)
-### Validation
+### Versionbits
-- #35209 validation: correct lifetime of precomputed tx data
-- #35465 coins: compact chainstate regularly
+- #34779 BIP 323: reserve version bits 5-28 as extra nonce space
-### Leveldb
+### P2P
-- #61(bitcoin-core/leveldb): Disable seek compaction
+- #35691 chainparams: delete my DNS seed
+- #35766 p2p: Assume v2transport for addresses from seeds
-### Wallet
+### Fuzz
-- #34358 wallet: fix removeprunedfunds bug with conflicting transactions
-- #34870 wallet: feebumper, fix crash when combined bump fee is unavailable
-- #34888 wallet: fix amount computed as boolean in coin selection
-- #35228 wallet: use outpoint when estimating input size
-
-### Net
-
-- #34093 netif: fix compilation warning in QueryDefaultGatewayImpl()
-- #34549 net: reduce log level for PCP/NAT-PMP NOT_AUTHORIZED failures
-
-### PSBT
-
-- #34272 psbt: Fix PSBTInputSignedAndVerified bounds assert
-- #34219 psbt: validate pubkeys in MuSig2 pubnonce/partial sig deserialization
-
-### Miniscript
-
-- #34434 miniscript: correct and_v() properties
-
-### Build
-
-- #34228 depends: Unset SOURCE_DATE_EPOCH in gen_id script
-- #34281 build: Temporarily remove confusing and brittle -fdebug-prefix-map
-- #34554 build: avoid exporting secp256k1 symbols
-- #34627 guix: use a temporary file over sponge, drop moreutils
-- #34713 depends: Allow building Qt packages after interruption
-- #34754 depends: Qt fixes for GCC 16 compatibility
-- #34787 build: fix native macOS deployment
-- #34848 cmake: Migrate away from deprecated SQLite3 target
-- #34956 depends, qt: Fix build on aarch64 macOS 26.4
-
-### Test
-
-- #34185 test: fix feature_pruning when built without wallet
-- #34282 qa: Fix Windows logging bug
-- #34390 test: allow overriding tar in get_previous_releases.py
-- #34409 test: use ModuleNotFoundError in interface_ipc.py
-- #34445 fuzz: Use AFL_SHM_ID for naming test directories
-- #34608 test: Fix broken --valgrind handling after bitcoin wrapper
-- #34690 test: Add missing timeout_factor to zmq socket
-- #34869 tests: applied PYTHON_GIL to the env for every test
-- #34918 fuzz: [refactor] Remove unused g_setup pointers
-- #35080 test: Add missing self.options.timeout_factor scale in tool_bitcoin_chainstate.py
-
-### Util
-
-- #34597 util: Fix UB in SetStdinEcho when ENOTTY
-
-### Doc
-
-- #34252 doc: add 433 (Pay to Anchor) to bips.md
-- #34413 doc: Remove outdated -fdebug-prefix-map section in dev notes
-- #34510 doc: fix broken bpftrace installation link
-- #34561 wallet: rpc: manpage: fix example missing `fee_rate` argument
-- #34671 doc: Update Guix install for Debian/Ubuntu
-- #34702 doc: Fix fee field in getblock RPC result
-- #34706 doc: Improve dependencies.md IPC documentation
-- #34789 doc: update build guides pre v31
-- #35283 doc: mention -DWITH_ZMQ=ON in BSD build guides
-
-### CI
-
-- #32513 ci: remove 3rd party js from windows dll gha job
-- #34344 ci: update GitHub Actions versions
-- #34453 ci: Always print low ccache hit rate notice
-- #34461 ci: Print verbose build error message in test-each-commit
-- #34802 ci: Bump GHA actions versions
-- #34815 ci: bump cirruslabs actions versions
-- #35202 ci: restore sockets in i686, no IPC job
-- #35378 ci: switch runners from cirrus to warpbuild
-- #35408 ci: 35378 followups
-
-### Misc
-
-- #35175 multi_index: fix compilation failure with boost >= 1.91
+- #35679 fuzz: Remove unused DeserializeFromFuzzingInput params overload
Credits
=======
Thanks to everyone who directly contributed to this release:
-- ANAVHEOBA
-- andrewtoth
-- brunoerg
-- Cory Fields
-- Daniel Pfeifer
+- ajtowns
- darosior
-- fanquake
-- furszy
- Hennadii Stepanov
-- jayvaliya
-- junbyjun1238
-- kevkevinpal
-- Lőrinc
-- m3dwards
-- marcofleon
-- MarcoFalke
-- mzumsande
-- nervana21
-- Padraic Slattery
-- ryanofsky
-- Sebastian Falbesoner
-- SomberNight
-- tboy1337
-- theuni
-- ToRyVand
-- willcl-ark
+- Martin Zumsande
+- sipa
As well as to everyone that helped with translations on
[Transifex](https://explore.transifex.com/bitcoin/bitcoin/).
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 2cbce2c56c7..25484254d2a 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -145,7 +145,6 @@ public:
// This is fine at runtime as we'll fall back to using them as an addrfetch if they don't support the
// service bits we want, but we should get them updated to support all service bits wanted by any
// release ASAP to avoid it where possible.
- vSeeds.emplace_back("seed.bitcoin.sipa.be."); // Pieter Wuille, only supports x1, x5, x9, and xd
vSeeds.emplace_back("dnsseed.bluematt.me."); // Matt Corallo, only supports x9
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch."); // Jonas Schnelli, only supports x1, x5, x9, and xd
vSeeds.emplace_back("seed.btc.petertodd.net."); // Peter Todd, only supports x1, x5, x9, and xd
diff --git a/src/net.cpp b/src/net.cpp
index 50988114d0b..7fbcd24b743 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -204,7 +204,7 @@ static std::vector ConvertSeeds(const std::vector &vSeedsIn)
while (!s.eof()) {
CService endpoint;
s >> endpoint;
- CAddress addr{endpoint, SeedsServiceFlags()};
+ CAddress addr{endpoint, SeedsAssumedServiceFlags()};
addr.nTime = rng.rand_uniform_delay(Now() - one_week, -one_week);
LogDebug(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
vSeedsOut.push_back(addr);
@@ -2365,7 +2365,7 @@ void CConnman::ThreadDNSAddressSeed()
const auto addresses{LookupHost(host, nMaxIPs, true)};
if (!addresses.empty()) {
for (const CNetAddr& ip : addresses) {
- CAddress addr = CAddress(CService(ip, m_params.GetDefaultPort()), requiredServiceBits);
+ CAddress addr = CAddress(CService(ip, m_params.GetDefaultPort()), SeedsAssumedServiceFlags());
addr.nTime = rng.rand_uniform_delay(Now() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
diff --git a/src/protocol.h b/src/protocol.h
index 804597b86d8..ca968ab0020 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -353,6 +353,14 @@ std::vector serviceFlagsToStr(uint64_t flags);
*/
constexpr ServiceFlags SeedsServiceFlags() { return ServiceFlags(NODE_NETWORK | NODE_WITNESS); }
+/**
+ * Service flags we assume for addresses obtained from the DNS seeds and the
+ * fixed seeds, which don't come with service flags attached.
+ * BIP324 support can be safely assumed because the vast majority of listening nodes signals NODE_P2P_V2, and if the
+ * assumption is wrong for a given peer we simply reconnect using v1 transport.
+ */
+constexpr ServiceFlags SeedsAssumedServiceFlags() { return ServiceFlags(SeedsServiceFlags() | NODE_P2P_V2); }
+
/**
* Checks if a peer with the given service flags may be capable of having a
* robust address-storage DB.
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index b7dea44b0b2..0b7c2d63072 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -55,14 +55,6 @@ namespace {
struct invalid_fuzzing_input_exception : public std::exception {
};
-template
-DataStream Serialize(const T& obj, const P& params)
-{
- DataStream ds{};
- ds << params(obj);
- return ds;
-}
-
template
T Deserialize(DataStream&& ds, const P& params)
{
@@ -71,18 +63,6 @@ T Deserialize(DataStream&& ds, const P& params)
return obj;
}
-template
-void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj, const P& params)
-{
- DataStream ds{buffer};
- try {
- ds >> params(obj);
- } catch (const std::ios_base::failure&) {
- throw invalid_fuzzing_input_exception();
- }
- assert(buffer.empty() || !Serialize(obj, params).empty());
-}
-
template
DataStream Serialize(const T& obj)
{
@@ -114,7 +94,7 @@ void DeserializeFromFuzzingInput(FuzzBufferType buffer, T&& obj)
template
void AssertEqualAfterSerializeDeserialize(const T& obj, const P& params)
{
- assert(Deserialize(Serialize(obj, params), params) == obj);
+ assert(Deserialize(Serialize(params(obj)), params) == obj);
}
template
void AssertEqualAfterSerializeDeserialize(const T& obj)
diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp
index 5a7722d8708..1b15cb8c57a 100644
--- a/src/test/fuzz/versionbits.cpp
+++ b/src/test/fuzz/versionbits.cpp
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
@@ -31,7 +32,7 @@ public:
{
assert(dep.period > 0);
assert(dep.threshold <= dep.period);
- assert(0 <= dep.bit && dep.bit < 32 && dep.bit < VERSIONBITS_NUM_BITS);
+ assert(0 <= dep.bit && dep.bit < 32 && dep.bit < VERSIONBITS_MAX_NUM_BITS);
assert(0 <= dep.min_activation_height);
}
@@ -126,7 +127,7 @@ FUZZ_TARGET(versionbits, .init = initialize)
assert(0 < dep.threshold && dep.threshold <= dep.period); // must be able to both pass and fail threshold!
// select deployment parameters: bit, start time, timeout
- dep.bit = fuzzed_data_provider.ConsumeIntegralInRange(0, VERSIONBITS_NUM_BITS - 1);
+ dep.bit = fuzzed_data_provider.ConsumeIntegralInRange(0, VERSIONBITS_MAX_NUM_BITS - 1);
if (always_active_test) {
dep.nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
diff --git a/src/test/util/versionbits.h b/src/test/util/versionbits.h
new file mode 100644
index 00000000000..478b7882fab
--- /dev/null
+++ b/src/test/util/versionbits.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2026-present The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_UTIL_VERSIONBITS_H
+#define BITCOIN_TEST_UTIL_VERSIONBITS_H
+
+#include
+
+/** Total possible bits available for versionbits per original BIP 9 specification */
+static constexpr int VERSIONBITS_MAX_NUM_BITS{29};
+
+#endif // BITCOIN_TEST_UTIL_VERSIONBITS_H
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 9de57393282..df00b08e6fd 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -453,9 +454,19 @@ BOOST_FIXTURE_TEST_CASE(versionbits_computeblockversion, BlockVersionTest)
// not take precedence over STARTED/LOCKED_IN. So all softforks on
// the same bit might overlap, even when non-overlapping start-end
// times are picked.
- const uint32_t dep_mask{uint32_t{1} << chainParams->GetConsensus().vDeployments[dep].bit};
+ const auto& dep_info = chainParams->GetConsensus().vDeployments[dep];
+ const uint32_t dep_mask{uint32_t{1} << dep_info.bit};
BOOST_CHECK(!(chain_all_vbits & dep_mask));
chain_all_vbits |= dep_mask;
+ BOOST_CHECK(0 <= dep_info.bit && dep_info.bit < VERSIONBITS_MAX_NUM_BITS);
+ if (chain_type != ChainType::REGTEST) {
+ if (dep == Consensus::DEPLOYMENT_TESTDUMMY) {
+ BOOST_CHECK_EQUAL(dep_info.nStartTime, Consensus::BIP9Deployment::NEVER_ACTIVE);
+ BOOST_CHECK_EQUAL(dep_info.nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);
+ } else {
+ BOOST_CHECK(dep_info.bit < VERSIONBITS_NUM_BITS);
+ }
+ }
check_computeblockversion(vbcache, chainParams->GetConsensus(), dep);
}
}
diff --git a/src/versionbits.h b/src/versionbits.h
index abd671b4efd..767e9e65fc8 100644
--- a/src/versionbits.h
+++ b/src/versionbits.h
@@ -21,8 +21,8 @@ static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4;
static const int32_t VERSIONBITS_TOP_BITS = 0x20000000UL;
/** What bitmask determines whether versionbits is in use */
static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL;
-/** Total bits available for versionbits */
-static const int32_t VERSIONBITS_NUM_BITS = 29;
+/** Total bits available for versionbits (BIP 323) */
+static const int32_t VERSIONBITS_NUM_BITS = 5;
/** Opaque type for BIP9 state. See versionbits_impl.h for details. */
enum class ThresholdState : uint8_t;
@@ -72,7 +72,8 @@ struct BIP9GBTStatus {
};
/** BIP 9 allows multiple softforks to be deployed in parallel. We cache
- * per-period state for every one of them. */
+ * per-period state for every one we implement and warning state for each
+ * BIP 323 allowed bit. */
class VersionBitsCache
{
private:
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py
index 96ec7c570fa..4e8049dd3a9 100755
--- a/test/functional/feature_versionbits_warning.py
+++ b/test/functional/feature_versionbits_warning.py
@@ -18,8 +18,13 @@ from test_framework.test_framework import BitcoinTestFramework
VB_PERIOD = 144 # versionbits period length for regtest
VB_THRESHOLD = 108 # versionbits activation threshold for regtest
VB_TOP_BITS = 0x20000000
-VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
+
+# Choose a bit unassigned to any deployment, or start the
+# node with the deployment matching this bit disabled.
+VB_UNKNOWN_BIT = 3
VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT)
+VB_IGNORED_BIT = 5
+VB_IGNORED_VERSION = VB_TOP_BITS | (1 << VB_IGNORED_BIT)
WARN_UNKNOWN_RULES_ACTIVE = f"Unknown new rules activated (versionbit {VB_UNKNOWN_BIT})"
VB_PATTERN = re.compile("Unknown new rules activated.*versionbit")
@@ -76,11 +81,24 @@ class VersionBitsWarningTest(BitcoinTestFramework):
assert not VB_PATTERN.match(",".join(node.getmininginfo()["warnings"]))
assert not VB_PATTERN.match(",".join(node.getnetworkinfo()["warnings"]))
+ self.log.info("Check that there is no warning if previous VB_BLOCKS have VB_PERIOD blocks with ignored versionbits version.")
+ # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit
+ self.send_blocks_with_version(peer, VB_THRESHOLD, VB_IGNORED_VERSION)
+ self.generatetoaddress(node, VB_PERIOD - VB_THRESHOLD, node_deterministic_address)
+
+ # Move the ignored deployment state to ACTIVE and make sure we're out of IBD.
+ self.generatetoaddress(node, VB_PERIOD, node_deterministic_address)
+ self.wait_until(lambda: not node.getblockchaininfo()['initialblockdownload'])
+
+ # Check that we're not getting any versionbit-related warnings in get*info()
+ assert not VB_PATTERN.match(", ".join(node.getmininginfo()["warnings"]))
+ assert not VB_PATTERN.match(", ".join(node.getnetworkinfo()["warnings"]))
+
+ self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.")
# Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit
self.send_blocks_with_version(peer, VB_THRESHOLD, VB_UNKNOWN_VERSION)
self.generatetoaddress(node, VB_PERIOD - VB_THRESHOLD, node_deterministic_address)
- self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.")
# Mine a period worth of expected blocks so the generic block-version warning
# is cleared. This will move the versionbit state to ACTIVE.
self.generatetoaddress(node, VB_PERIOD, node_deterministic_address)