{"number":434,"title":"Peer Feature Negotiation","authors":["Anthony Towns"],"status":"Complete","type":"Specification","layer":"Peer Services","created":"2026-01-14","license":"BSD-2-Clause","version":"1.0.0","requires":[],"replaces":[],"replacedBy":[],"discussion":["https://gnusha.org/pi/bitcoindev/aUUXLgEUCgGb122o@erisian.com.au/T/#u","https://gnusha.org/pi/bitcoindev/20200821023647.7eat4goqqrtaqnna@erisian.com.au/"],"abstract":"This BIP defines a peer-to-peer (P2P) message that can be used for announcements and negotiation related to support of new peer-to-peer features.","eli5":"Defines a peer-to-peer message that nodes can exchange while first connecting, to announce and agree on support for new network features. This gives a cleaner, uniform way to roll out future upgrades to how Bitcoin nodes communicate.","categories":["network"],"filename":"bip-0434.md","githubUrl":"https://github.com/bitcoin/bips/blob/master/bip-0434.md","format":"markdown","readingMinutes":10,"inbound":1,"revisions":5,"impact":31,"core":false,"references":[],"lastModified":"2026-06-11","html":"<h2 id=\"abstract\">Abstract</h2>\n<p>This BIP defines a peer-to-peer (P2P) message that can be used for\nannouncements and negotiation related to support of new peer-to-peer\nfeatures.</p>\n<h2 id=\"motivation\">Motivation</h2>\n<p>Historically, new peer-to-peer protocol changes have been tied to\nbumping the protocol version, so that nodes know to only attempt\nfeature negotiation with peers that support the feature. Coordinating\nthe protocol version across implementations, when different clients may\nhave different priorities for features to implement, is an unnecessary\nburden in the upgrade process for P2P features that do not require\nuniversal support. And at a more philosophical level, having the P2P\nprotocol be <a href=\"https://github.com/bitcoin/bitcoin/pull/20564#issuecomment-738456560\">permissionlessly extensible</a>, with no\ncoordination required between implementations or developers, seems ideal\nfor a decentralized system.</p>\n<p>Many earlier P2P protocol upgrades were implemented as new messages\nsent after a peer connection is set up (ie, after receipt of a <code>verack</code>\nmessage by both sides). See <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki\">BIP 130 (sendheaders)</a>, <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki\">BIP 133\n(feefilter)</a>, and <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki\">BIP 152 (compact blocks)</a> for some\nexamples. However, for some P2P upgrades, it is helpful to perform\nfeature negotiation prior to a connection being fully established\n(ie, prior to the <code>verack</code> being received by both sides). <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki\">BIP 155\n(addrv2)</a> and <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki\">BIP 339 (wtxid-relay)</a> are examples of\nthis approach, which involves sending and receiving a single new message\n(<code>sendaddrv2</code> and <code>wtxidrelay</code> respectively), in between <code>version</code> and\n<code>verack</code> to indicate support of the new feature.</p>\n<p>In all these cases, sending new messages on the network raises the\nquestion of what non-implementing software will do with such messages. The\ncommon behavior observed on the network was for software to ignore\nunknown messages received from a peer, so these proposals posed minimal\nrisk of potential network partitioning. In fact, supporting protocol\nextensibility in this manner was given as an explicit reason to ignore\nunknown messages in Bitcoin&#39;s <a href=\"https://github.com/benjiqq/bitcoinArchive/blob/master/bitcoin0.1/src/main.cpp#L2035-L2039\">first release</a>.</p>\n<p>However, if nodes respond to unknown messages by disconnecting, then\nthe network might partition in the future as incompatible software is\ndeployed. And in fact, some clients on the network have historically\ndiscouraged or disallowed unknown messages, both between <code>version</code>\nand <code>verack</code> (eg, Bitcoin Core discouraged such messages between\n<a href=\"https://github.com/bitcoin/bitcoin/pull/9720\">PR#9720</a> and <a href=\"https://github.com/bitcoin/bitcoin/pull/19723\">PR#19723</a>, and btcd disallowed\nsuch messages until <a href=\"https://github.com/btcsuite/btcd/pull/1812\">PR#1812</a>, but see also discussion in\n<a href=\"https://github.com/btcsuite/btcd/issues/1661\">#1661</a>), as well as after <code>verack</code>.</p>\n<p>To maximise compatibility with such clients, most of these BIPs require\nthat peers bump the protocol version:</p>\n<ul>\n<li><a href=\"https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki\">BIP 130</a> requires version 70012 or higher,</li>\n<li><a href=\"https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki\">BIP 133</a> requires version 70013 or higher,</li>\n<li><a href=\"https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki\">BIP 152</a> recommends version 70014/70015 or higher, and</li>\n<li><a href=\"https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki\">BIP 339</a> requires version 70016 or higher.</li>\n</ul>\n<p>And while <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki\">BIP 155</a> does not specify a minimum protocol version,\nimplementations have <a href=\"https://github.com/bitcoin/bitcoin/pull/20564\">added</a> a de facto requirement of version\n70016 or higher.</p>\n<p>In this BIP, we propose codifying and generalising the mechanism used by\n<a href=\"https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki\">BIP 339</a> for future P2P upgrades, by adding a single new feature\nnegotiation message that can be reused for advertising arbitrary new\nfeatures, and requiring that implementing software ignore unknown features\nthat might be advertised. This allows future upgrades to negotiate new\nfeatures by exchanging messages prior to exchanging <code>verack</code> messages,\nwithout concerns of being unnecessarily disconnected by a peer which\ndoesn&#39;t understand the messages, and without needing to coordinate\nupdating the protocol version.</p>\n<h2 id=\"specification\">Specification</h2>\n<p>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;,\n&quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be\ninterpreted as described in RFC 2119.</p>\n<p>For the purposes of this section, <code>CompactSize</code> refers to the\nvariable-length integer encoding used across the existing P2P protocol\nto encode array lengths, among other things, in 1, 3, 5 or 9 bytes. Only\n<code>CompactSize</code> encodings which are minimally-encoded (ie the shortest\nlength possible) are used by this specification.</p>\n<p>Nodes implementing this BIP:</p>\n<ul>\n<li>MUST advertise a protocol version number <code>&gt;= 70017</code>,</li>\n<li>MUST NOT send <code>feature</code> messages to peers that advertise a protocol\nversion number <code>&lt; 70017</code>,</li>\n<li>MUST accept <code>feature</code> messages received after the <code>version</code> message\nand before the <code>verack</code> message, and</li>\n<li>MUST NOT send <code>feature</code> messages after sending the <code>verack</code> message.</li>\n</ul>\n<p>In addition, nodes implementing this BIP:</p>\n<ul>\n<li>SHOULD ignore unknown messages received after the <code>version</code> message\nand before the <code>verack</code> message,</li>\n<li>MAY ignore <code>feature</code> messages sent after <code>verack</code>, and</li>\n<li>MAY disconnect peers who send <code>feature</code> messages after <code>verack</code>.</li>\n</ul>\n<p>Feature specifications based on this BIP:</p>\n<ul>\n<li>MUST forbid sending messages it introduces after <code>verack</code> to a peer\nthat has not indicated support for the feature via a <code>feature</code>\nmessage.</li>\n</ul>\n<h3 id=\"feature-message\"><code>feature</code> message</h3>\n<p>The payload of the <code>feature</code> message contains exactly the following data:</p>\n<table>\n<thead>\n<tr>\n<th>Type</th>\n<th>Name</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>string</td>\n<td><code>featureid</code></td>\n<td>Unique identifier for the feature</td>\n</tr>\n<tr>\n<td>byte-vector</td>\n<td><code>featuredata</code></td>\n<td>Feature-specific configuration data</td>\n</tr>\n</tbody></table>\n<p>The <code>featureid</code> is encoded in the usual way, that is, as a <code>CompactSize</code>\nspecifying the string length, followed by that many bytes. The string\nlength MUST be between 4[^feature-id-min] and 80[^feature-payload-max],\ninclusive. The string SHOULD include only printable ASCII characters\n(ie, each byte should have a value between 32 and 126, inclusive).</p>\n<p>Likewise, <code>featuredata</code> is encoded as a <code>CompactSize</code> specifying the\nbyte-vector size, followed by that many bytes. How these bytes are\ninterpreted is part of the feature&#39;s specification. The byte-vector\nsize MUST NOT be more than 512 bytes[^feature-payload-max]. Note that\nthe <code>featuredata</code> field is not optional, so if no data is required,\nan empty vector should be provided, ie serialized as <code>CompactSize</code> of 0.</p>\n<p>The <code>featureid</code> MUST be a globally unique identifier for the feature.</p>\n<p>For features published as a BIP, the <code>featureid</code> SHOULD be the assigned\nBIP number, eg &quot;BIP434&quot;, or be based on the BIP number (eg, &quot;BIP434v2&quot;\nwhere the &quot;v2&quot; suffix covers versioning, or &quot;BIP434.3&quot; where the &quot;.3&quot;\nsuffix covers part 3 of the BIP). For experimental features that do not\n(yet) have a BIP number assigned, some other unique identifier MUST be\nchosen, such as a URL to the repository where development is taking\nplace, or the sha256 digest of some longer reference.</p>\n<p>Nodes implementing this BIP MUST ignore <code>feature</code> messages specifying a\n<code>featureid</code> they do not support, so long as the payload conforms to the\nrequirements above.</p>\n<p>Nodes implementing this BIP MAY disconnect peers that send <code>feature</code>\nmessages where the <code>feature</code> message&#39;s payload cannot be correctly\nparsed (including having missing or additional data), even if they do\nnot recognise the <code>featureid</code>.</p>\n<h4 id=\"feature-message-1-byte-identifier\"><code>feature</code> message 1-byte identifier</h4>\n<p>Nodes implementing both this BIP and <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki\">BIP 324 (v2 P2P encrypted\ntransport)</a> MUST treat a message with a 1-byte <code>message_type</code>\nequal to <code>37</code> that is received prior to <code>verack</code> as the <code>feature</code> message.</p>\n<h3 id=\"feature-negotiation\">Feature negotiation</h3>\n<p>It is RECOMMENDED that feature negotiation be designed and implemented\nas follows:</p>\n<ul>\n<li>all <code>feature</code> messages and the <code>verack</code> message should be sent\nimmediately on receipt of the peer&#39;s <code>version</code> message</li>\n<li>any negotiation calculations should be performed immediately on\nreceipt of the peer&#39;s <code>verack</code> message</li>\n</ul>\n<p>This structure is fairly easy to implement, and avoids introducing any\nsignificant latency that might result from more interactive negotiation\nmethods.</p>\n<p>Feature specifications defining a <code>featureid</code> MAY make use of the\nfollowing approaches:</p>\n<h4 id=\"feature-advertisement\">Feature advertisement:</h4>\n<ol>\n<li>Send a <code>feature</code> message advertising the <code>featureid</code> unconditionally</li>\n<li>Accept messages related to the feature unconditionally</li>\n<li>Only send messages defined by the feature if the peer sent\na valid <code>feature</code> message for the <code>featureid</code>.</li>\n</ol>\n<p>This approach is appropriate for many simple features that define\nnew messages, particularly where an implementation might only\nimplement sending or receiving a message, but not both, eg <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki\">BIP 35\n(mempool)</a>.</p>\n<h4 id=\"feature-coordination\">Feature coordination:</h4>\n<ol>\n<li>Send a <code>feature</code> message advertising the <code>featureid</code> unconditionally</li>\n<li>Check if the peer sends the same <code>feature</code> message (or a compatible\none), and enable the feature for this peer if so.</li>\n<li>Only send/accept messages or encode data items according to the\nfeature&#39;s specification if the feature is enabled for this peer.</li>\n</ol>\n<p>This approach is appropriate for upgrades to data encoding in\nP2P messages, eg <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki\">BIP 339 (wtxidrelay)</a> or <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki\">BIP 155\n(addrv2)</a>.</p>\n<h4 id=\"feature-versioning\">Feature versioning:</h4>\n<ol>\n<li>Send <code>feature</code> messages for multiple incompatible features, eg\n<code>BIP434v3</code>, <code>BIP434v2</code>, <code>BIP434v1</code>, ordered from most preferred\nto least.</li>\n<li>Track the corresponding <code>feature</code> messages from your peer.</li>\n<li>If you were the listening peer, enable your highest preference feature\nthat your peer also supports.</li>\n<li>If you were the initiating peer, enable the first feature that your\npeer announced, that you also support.</li>\n<li>For example if the listening peer sends <code>BIP434v3</code>, <code>BIP434v2</code>,\n<code>BIP434v1</code>, and the initiating peer sends <code>BIP434v1</code>, <code>BIP434v2</code>,\nthen the listening peer should select <code>BIP434v2</code> when <code>verack</code>\nis received, and the initiating peer should select <code>BIP434v2</code>\nas soon as <code>feature BIP434v2</code> is received.</li>\n<li>Conversely, if the initiating peer sends <code>BIP434v3</code>, <code>BIP434v2</code>,\n<code>BIP434v1</code>, and the listening peer sends <code>BIP434v1</code>, <code>BIP434v2</code>,\nthen the listening peer should select <code>BIP434v1</code> when <code>verack</code>\nis received, and the initiating peer should select <code>BIP434v1</code>\nas soon as <code>feature BIP434v1</code> is received.</li>\n<li>In most cases, implementations should simply advertise incompatible\nfeatures in order from most recent to oldest, on the basis that\nthe only reason to make incompatible updates is because there are\nsignificant improvements. Exceptions to that may occur when two\nincompatible features are both receiving active development, or\nwhen an implementation has only partially implemented the latest\nspec, and the older spec is better supported (and thus should be\nlisted first, as the preferred protocol to adopt).</li>\n</ol>\n<p>This approach may be appropriate when making substantial changes to a\ndeployed protocol and backwards compatibility is desirable on a short-term\nbasis, or when there is disagreement amongst implementations or users\nas to which approach is most desirable.</p>\n<h2 id=\"considerations\">Considerations</h2>\n<p>The advantage this approach has over bumping the protocol version\nnumber when introducing new P2P messages or data structures, is that no\ncoordination is required (that is, there is no longer a question whether\nversion &quot;n+1&quot; belongs to Alice&#39;s new feature, or Bob&#39;s new feature),\nand there is no implication that supporting each new feature means all\nprior features are also supported.</p>\n<p>The advantage this approach has over defining new messages for each\nfeature is that the <code>featureid</code> can be much longer (at up to 80\nbytes) than a message type id (which are limited to 12 bytes). With a\n<a href=\"https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki\">BIP 324</a> one-byte <code>message_type</code>, the overhead compared to that\napproach is also kept small.</p>\n<p>This approach is largely equivalent to adding a <a href=\"https://gnusha.org/pi/bitcoindev/B514142F-382B-4D49-B68D-0115ECBD1D79@voskuil.org/\">payload to the <code>verack</code>\nmessage</a> (eg, a vector of <code>featureid</code>, <code>featuredata</code>\npairs). It was chosen because:</p>\n<ul>\n<li>it retains compatibility with any implementations that expect <code>verack</code>\nto have no payload;</li>\n<li>it allows peers to process each feature request individually, rather than\nhaving to first load the configuration information for all features into\nmemory at once (in order to validate the message&#39;s checksum), and then\ndeal with each feature&#39;s configuration;</li>\n<li>limiting the maximum message payload size you accept (eg to 4MB)\ndoes not limit the number of features you can accept; and</li>\n<li>we have experience with negotiating features with individual messages,\nbut no experience with doing so via <code>verack</code> payload.</li>\n</ul>\n<p>A mild disadvantage compared to using a <code>verack</code> payload is that this\napproach allows the possibility of interactive feature negotiation prior\nto <code>verack</code>, which would make negotiation more complex and increase\nlatency. However interactive feature negotiation is always possible\nsimply by having the initiating peer disconnect and reconnect after\ndiscovering the listening peer&#39;s supported features.</p>\n<p>This specification attempts to maximise compatibility with implementations\nthat prefer to fully validate each message received:</p>\n<ul>\n<li><code>feature</code> messages, even for unknown features, must always be fully\nparseable into a <code>featureid</code> and <code>featuredata</code></li>\n<li>Ignoring unknown messages prior to <code>verack</code> is only a recommendation,\nnot a requirement, so compliant implementations may disconnect on an\nunknown message that cannot be validated.</li>\n<li>Sending unknown messages after <code>verack</code> is explicitly forbidden,\nin so far as that is possible.</li>\n</ul>\n<h2 id=\"reference-implementation\">Reference implementation</h2>\n<p>This feature was implemented in Bitcoin Core <a href=\"https://github.com/bitcoin/bitcoin/pull/35221\">PR#35221</a>,\nwhich may be used as a reference implementation.</p>\n<h2 id=\"backward-compatibility\">Backward compatibility</h2>\n<p>Clients specifying a version number prior to <code>70017</code> remain fully\ncompatible with this change.</p>\n<p>Clients specifying a version number of <code>70017</code> or higher that do not\nimplement this BIP remain fully compatible provided they do not disconnect\npeers upon receiving unexpected messages received between <code>version</code> and\n<code>verack</code>.</p>\n<h2 id=\"acknowledgements\">Acknowledgements</h2>\n<p>Much of the logic here, and much of the text in the motivation section,\nis based on Suhas Daftuar&#39;s 2020 post on <a href=\"https://gnusha.org/pi/bitcoindev/CAFp6fsE=HPFUMFhyuZkroBO_QJ-dUWNJqCPg9=fMJ3Jqnu1hnw@mail.gmail.com/\">Generalizing feature\nnegotiation</a>.</p>\n<h2 id=\"copyright\">Copyright</h2>\n<p>This BIP is licensed under the 2-clause BSD license.</p>\n<p>[^feature-id-min]: The minimum <code>featureid</code> length of 4 characters\ncorresponds with a &quot;BIPx&quot; string for BIPs in the range 1-9. Longer\nidentifiers than this will almost always be needed in order to meet the\n&quot;globally unique&quot; requirement.</p>\n<p>[^feature-payload-max]: The maximum values for the <code>featureid</code> and\n<code>featuredata</code> lengths serve only to bound the volume of the feature\nmessage payload, particularly as this data will be automatically\nadvertised even to peers that do not support the features in question.</p>\n","toc":[{"id":"abstract","title":"Abstract","level":2},{"id":"motivation","title":"Motivation","level":2},{"id":"specification","title":"Specification","level":2},{"id":"feature-message","title":"feature message","level":3},{"id":"feature-message-1-byte-identifier","title":"feature message 1-byte identifier","level":4},{"id":"feature-negotiation","title":"Feature negotiation","level":3},{"id":"feature-advertisement","title":"Feature advertisement:","level":4},{"id":"feature-coordination","title":"Feature coordination:","level":4},{"id":"feature-versioning","title":"Feature versioning:","level":4},{"id":"considerations","title":"Considerations","level":2},{"id":"reference-implementation","title":"Reference implementation","level":2},{"id":"backward-compatibility","title":"Backward compatibility","level":2},{"id":"acknowledgements","title":"Acknowledgements","level":2},{"id":"copyright","title":"Copyright","level":2}],"history":{"totalCommits":5,"firstCommit":"2025-12-06T07:27:13+10:00","lastUpdated":"2026-06-11T15:15:57+10:00","events":[{"sha":"b14d7c34e5ffa4dd910eeba3df4f92af6a9609d4","date":"2026-06-11T15:15:57+10:00","author":"Anthony Towns","message":"BIP-434: Add reference implementation, bump to 1.0.0, mark complete","url":"https://github.com/bitcoin/bips/commit/b14d7c34e5ffa4dd910eeba3df4f92af6a9609d4","kind":"status"},{"sha":"18ff6bb77b921e6952c11895c203bf1b4e0eaf2f","date":"2026-05-29T15:28:41+10:00","author":"Anthony Towns","message":"BIP-434: Various rationale edits","url":"https://github.com/bitcoin/bips/commit/18ff6bb77b921e6952c11895c203bf1b4e0eaf2f","kind":"edit"},{"sha":"3709d73c2f168ac3977bab9329e53cd9d7008612","date":"2026-02-03T14:47:51+10:00","author":"Anthony Towns","message":"BIP 434: fix license inconsistency","url":"https://github.com/bitcoin/bips/commit/3709d73c2f168ac3977bab9329e53cd9d7008612","kind":"edit"},{"sha":"a50c0ea32b104832d15b10a3d65bc77ee8df98da","date":"2026-01-31T17:25:09+10:00","author":"Anthony Towns","message":"BIP324, BIP434: Assign message type id for \"feature\" message","url":"https://github.com/bitcoin/bips/commit/a50c0ea32b104832d15b10a3d65bc77ee8df98da","kind":"edit"},{"sha":"9630c4c8d076b289e24d7cad818d43440ce613ae","date":"2025-12-06T07:27:13+10:00","author":"Anthony Towns","message":"BIP434: p2p feature negotiation","url":"https://github.com/bitcoin/bips/commit/9630c4c8d076b289e24d7cad818d43440ce613ae","kind":"edit"}]}}