[BIP Draft] P2P UTXO Set Sharing

199 views
Skip to first unread message

Fabian

unread,
May 5, 2026, 11:39:56 AM (8 days ago) May 5
to bitco...@googlegroups.com
Dear list,

I am sharing a BIP draft for sharing the UTXO set over the P2P network, an old idea that makes it possible to utilize AssumeUTXO without sourcing a UTXO set dump from a third party source. You can find the full text below or comment on the BIPs repository pull directly: https://github.com/bitcoin/bips/pull/2137

Fabian


```
  BIP: ?
  Layer: Peer Services
  Title: P2P UTXO Set Sharing
  Authors: Fabian Jahr <fj...@protonmail.com>
  Status: Draft
  Type: Specification
  Assigned: ?
  Discussion: ?
  Version: 0.2.0
  License: BSD-2-Clause
```

## Abstract

This BIP defines a P2P protocol extension for sharing full UTXO sets between peers. It introduces
a new service bit `NODE_UTXO_SET`, four new P2P messages (`getutxotree`, `utxotree`, `getutxoset`,
`utxoset`), and a chunk-hash list anchored to a Merkle root known to the requesting node, enabling
per-chunk verification. This allows nodes to bootstrap from a recent height by obtaining the
required UTXO set directly from the P2P network via mechanisms such as assumeutxo.

## Motivation

The assumeutxo feature (implemented in Bitcoin Core) allows nodes to begin operating from a serialized
UTXO set while validating
historical blocks in the background. However, there is currently no canonical source for obtaining this
data. Users must either generate one themselves from a fully synced node (using `dumptxoutset` in
Bitcoin Core), or download one from a third party.

By enabling UTXO set sharing over the P2P network, new nodes can obtain the data directly from
peers, removing the dependency on external infrastructure.

## Specification

The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be
interpreted as described in RFC 2119.

### Service Bit

| Name | Bit | Description |
|------|-----|-------------|
| `NODE_UTXO_SET` | 12 (0x1000) | The node can serve complete UTXO set data for at least one height. |

A node MUST NOT set this bit unless it has at least one full UTXO set available to serve.
A node signaling `NODE_UTXO_SET` MUST be capable of responding to `getutxotree` and `getutxoset`
requests for every UTXO set it is willing to serve, including the full chunk-hash list and every
chunk of those sets.

### Data Structures

#### Serialized UTXO Set

The serialized UTXO set uses the format established by the Bitcoin Core RPC `dumptxoutset` (as of Bitcoin Core v31).

**Header (55 bytes):**

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `magic` | `bytes` | 5 | `0x7574786fff` (ASCII `utxo` + `0xff`). |
| `version` | `uint16_t` | 2 | Format version. |
| `network_magic` | `bytes` | 4 | Network message start bytes. |
| `base_height` | `uint32_t` | 4 | Block height of the UTXO set. |
| `base_blockhash` | `uint256` | 32 | Block hash of the UTXO set. |
| `coins_count` | `uint64_t` | 8 | Total number of coins (UTXOs) in the set. |

**Body (coin data):**

Coins are grouped by transaction hash. For each group:

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `txid` | `uint256` | 32 | Transaction hash. |
| `num_coins` | `compact_size` | 1–9 | Number of outputs for this txid. |

For each coin in the group:

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `vout_index` | `compact_size` | 1–9 | Output index. |
| `coin` | `Coin` | variable | Serialized coin (varint-encoded code for height/coinbase, then compressed txout). |

Coins are ordered lexicographically by outpoint (txid, then vout index), matching the LevelDB iteration
order of the coins database.

#### Chunk Merkle Tree

The serialized UTXO set (header + body) is split into chunks of exactly 3,900,000 bytes (3.9 MB). The
last chunk contains the remaining bytes and may be smaller.

The leaf hash for each chunk is `SHA256d(chunk_data)`. The tree is built as a balanced binary tree. When
the number of nodes at a level is odd, the last node is duplicated before hashing the next level.
Interior nodes are computed as `SHA256d(left_child || right_child)`.

The leaves are delivered to the node in a single `utxotree` response. A node that knows
the Merkle root for a given UTXO set checks a received list of leaves by recomputing the root and
comparing. The Merkle root is the sole trust input required to verify the integrity of the received UTXO set.

`SHA256d` denotes double-SHA256: `SHA256d(x) = SHA256(SHA256(x))`.

### Messages

#### `getutxotree`

Sent to request the chunk-hash list for a specific UTXO set.

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash identifying the requested UTXO set. |

A node that has advertised `NODE_UTXO_SET` and can serve the requested UTXO set MUST respond with
`utxotree`. If the serving node cannot fulfill the request, it MUST NOT respond. The requesting
node SHOULD apply a reasonable timeout and try another peer.

#### `utxotree`

Sent in response to `getutxotree`, delivering the full chunk-hash list along with per-snapshot
metadata.

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash this data corresponds to. |
| `version` | `uint16_t` | 2 | Format version of the serialized UTXO set. |
| `data_length` | `uint64_t` | 8 | Total size of the serialized UTXO set in bytes (header + body). |
| `num_chunks` | `compact_size` | 1–9 | Number of chunks the serialized UTXO set is split into. |
| `chunk_hashes` | `uint256[]` | 32 × `num_chunks` | The ordered list of chunk hashes. |

Upon receiving a `utxotree` message, the node MUST recompute the Merkle root from
`chunk_hashes` and compare it against the Merkle root it knows for the corresponding UTXO set. If
the roots do not match, the node MUST discard the response and MUST disconnect the peer.

#### `getutxoset`

Sent to request a single chunk of UTXO set data. The requesting node MUST have received a `utxotree`
for the corresponding UTXO set before sending this message.

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash identifying the requested UTXO set. |
| `chunk_index` | `uint32_t` | 4 | Zero-based index of the requested chunk. |

If the serving node cannot fulfill the request, it MUST NOT respond. The requesting node SHOULD apply
a reasonable timeout and try another peer.

#### `utxoset`

Sent in response to `getutxoset`, delivering one chunk.

| Field | Type | Size | Description |
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash this data corresponds to. |
| `chunk_index` | `uint32_t` | 4 | Zero-based index of this chunk. |
| `data` | `bytes` | variable | Chunk payload, exactly 3.9 MB except for the last chunk. |

The transfer is receiver-driven: the requesting node sends one `getutxoset` per chunk. Chunks MAY be
requested in any order and from different peers.

Upon receiving a `utxoset` message, the node MUST compute `SHA256d(data)` and compare it against
`chunk_hashes[chunk_index]` from the `utxotree` it accepted for this UTXO set. If the hashes do not
match, the node MUST discard the chunk and MUST disconnect the peer. A node SHOULD also disconnect
a peer that sends a `utxoset` message with fields (`chunk_index`, `block_hash`) that do not match
the outstanding request.

After all chunks have been received, the node SHOULD parse the reassembled UTXO set against the
serialized UTXO set format to confirm it is well-formed.

### Protocol Flow

1. The requesting node identifies peers advertising `NODE_UTXO_SET`.
2. The requesting node sends `getutxotree` for the desired block hash to one or more of these peers.
3. Each peer responds with `utxotree`. The requesting node verifies the response by recomputing
   the Merkle root against a value it knows for the given UTXO set, either from a trusted source
   or by selecting a root with agreement among multiple peers.
4. The requesting node downloads chunks via `getutxoset`/`utxoset` exchanges, verifying each chunk
   against its entry in the accepted `utxotree` on receipt. On verification failure the peer is
   disconnected and download continues from another peer without losing already-verified chunks.
5. After all chunks are received, the node parses the reassembled UTXO set against the serialized
   UTXO set format to confirm that it is well-formed.

Serving nodes are free to limit the number of concurrent and repeated transfers per peer at their own
discretion to manage resource consumption.

## Rationale

**Usage of service bit 12:** Service bits allow selective peer discovery through
DNS seeds and addr relay. Bit 12 is chosen as the next unassigned bit after `NODE_P2P_V2` (bit 11, BIP 324).

**Direct request model:** Peers signal availability of UTXO sets via the `NODE_UTXO_SET`
service bit; the requesting node identifies the desired UTXO set by block hash when sending
`getutxotree`. The serving node responds only if it can serve that specific UTXO set.

**Per-chunk verification:** The chunk-hash list returned in `utxotree` enables each chunk to be verified
by direct lookup against the accepted list as it arrives, allowing immediate detection of corrupt data,
peer switching without data loss, and parallel download from multiple peers. The list itself is small
(~80 KB for a ~10 GB set). The specified serialization is deterministic, so all honest nodes produce
byte-identical output, guaranteeing Merkle root agreement.

**3.9 MB chunk size:** The number balances round trips (~2,560 for a ~10 GB set) against memory usage
for buffering and verifying a single chunk. Smaller chunks would increase protocol overhead; larger
chunks would increase memory pressure on constrained devices commonly used to run Bitcoin nodes.
Together with the additional message overhead, the `utxoset` message including the chunk data also
sits just below the theoretical maximum block size which means any implementation should be able to
handle messages of this size.

**Reusing the `dumptxoutset` format:** Avoids introducing a new serialization format and ensures
compatibility with UTXO sets already being generated and shared.

**Relationship to BIP 64:** BIP 64 defined a protocol for querying individual UTXOs by outpoint and is
now closed. This BIP addresses a different use case: bulk transfer of the entire UTXO set for node
bootstrapping.

## Reference Implementation

[Bitcoin Core implementation pull request](https://github.com/bitcoin/bitcoin/pull/35054)

## Copyright

This BIP is made available under the terms of the 2-clause BSD license. See

## Changelog

* __0.2.0__ (2026-05-04):
    * Dropped discovery before download approach, instead request the chunk-hash list via `getutxotree`/`utxotree`
    * Dropped per-chunk Merkle proofs; chunks verified directly against the chunk-hash list
    * Dropped `height` from requests (`block_hash` is the sole identifier); added format `version` to `utxotree`
    * Dropped references to the serialized hash; the Merkle root is the sole integrity check
* __0.1.0__ (2026-04-10):
    * Initial draft

Eric Voskuil

unread,
May 5, 2026, 12:17:53 PM (8 days ago) May 5
to Bitcoin Development Mailing List
Concept NACK. It's bad enough that nodes are formalizing this off network, but incorporating it into p2p is another level of awful.

Antoine Riard

unread,
May 5, 2026, 9:28:13 PM (8 days ago) May 5
to Bitcoin Development Mailing List
Hello Fabian, From a short read over the BIP, I'm wondering if the present BIP proposal wouldn't be better implemented as a feature on top of the BIP 434 (and that would be an opportunity to exercise the proposed mechanism). Keeping reserved a service bit means implementation that don't wish to support the feature don't have to parse / reserve it. Now, on the other hand it facilitates discovery at the peer layer by any bitcoin software. Second observation, there is no mention of the computational worst-case for the parsing and validation of the `utxotree`. What if the forwarding peer is an asshole and share you a crappy utxo set, where validity will be only asserted when you received and verify the latest utxo with the latest `utxoset`. There could be an intermediary "authentication" step a la BIP157 of the root itself, if you're peers assume-utxo servicing discovery is sane and you're connected to a least one honest peer that makes it harder to DoS the recipient. I'm worried it's a bit like BIP157 / BIP158 (or bloom filters fwiw), why a full-node implemention would go to bloat its p2p stack to support a client-server like flow (independently of the consideration that one find assume-utxo interesting as a validation model). Best, Antoine OTS hash: ba583724bad6f5251fd793abf626a598f64a1dcd9f5ff6b1f91e1cbd02c09774

Fabian

unread,
May 7, 2026, 5:39:57 PM (6 days ago) May 7
to Eric Voskuil, Bitcoin Development Mailing List

Hi Eric,


Thanks for sharing your feedback. I also read conversations on X so I am answering with those in mind as well even though not everything may have been spelled out in this thread explicitly.


Of course, the proposal is opt-in, just like AssumeUTXO itself. A node that does not use this feature is unaffected by it. Assumeutxo doesn’t change consensus, the header chain is validated before loading the UTXO set and full IBD still happens in the background. AssumeUTXO  is a UX improvement for those interested in running a fully validating node. The option to get started in a very limited amount of time even under significant hardware constraints can motivate users to choose a full node over an SPV client if startup time is relevant for their decision. And at some point of hardware constraints it definitely is, I think. In addition, it is a much easier decision for users to do IBD with assumevalid=0 as they are not required to wait for the completion of background IBD to take the next steps in their setup.


Also, this proposal only improves the sourcing of the UTXO set. Currently this needs to happen through some third party source and loaded into the node manually which comes with it’s own set of potential risks (privacy, malware), being able to rely on the P2P network as a secure source is preferable to that.


I think your main critique boils down to “this is a slippery slope” aside from your critique of assumeutxo and the Bitcoin Core architecture in general (see https://x.com/evoskuil/status/2052027207032164488). I can not refute critique of something that is not part of this proposal except for pointing out that what you are insinuating is not something I am working on or plan on working on and I am not aware of anyone working on skipping IBD and I would not endorse such a proposal if it were to be published. In contrast to some hypothetical dangerous future extension of this proposal that you are warning about, I am convinced that it does have real positive impact on users today, as I pointed out above.


Fabian


--
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/19616822-8a03-4de1-99be-72d50479208fn%40googlegroups.com.

Fabian

unread,
May 7, 2026, 6:09:15 PM (6 days ago) May 7
to Antoine Riard, Bitcoin Development Mailing List
Hi Antoine,

thanks for your feedback.

The idea to use BIP434 is indeed very tempting. I had lost track of that proposal for some time and that's why I didn't even think of it. I assumed it had stalled but I pinged AJ and there is now a stand-alone Bitcoin Core PR open for it. I will look over BIP434 again in detail and review the Bitcoin Core PR before I make a final decision on moving the proposal over, but my feeling right now is that this is likely to happen unless I am overlooking any roadblocks.

I am not sure I can follow your point on the computational worst case. If the node has the root of the Merkle tree of chunks embedded AssumeUTXO style or if it knows the root from somewhere else it will get an actual UTXO set. So I don't understand how the "crappy utxo set" would look like and get to the peer. I also can't really grasp the BIP157 scheme to help with this but that's probably because I am not understanding the issue to begin with. If you could give me a bit more details and/or a concrete example here that would be really great!

Thanks,
Fabian
--
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+...@googlegroups.com.

er...@voskuil.org

unread,
May 12, 2026, 12:02:46 PM (yesterday) May 12
to Fabian, Bitcoin Development Mailing List
Hi Fabain,

Thanks for the reply. Comments inline.

> AssumeUTXO is a UX improvement for those interested in running a fully
> validating node. The option to get started in
> a very limited amount of time even under significant hardware constraints
> can motivate users to choose a full node over an SPV client if startup time is
> relevant for their decision.

It's not at all clear to me how this is a UX improvement. Get started doing what?

> And at some point of hardware constraints it definitely is, I think.

This implies that that hardware constraints are somehow overcome by this, which is not the case.

> In addition, it is a much easier decision for users to do IBD
> with assumevalid=0 as they are not required to wait for the completion of
> background IBD to take the next steps in their setup.

These aren't limitations inherent in protocol. The implementation details of a given node aren't relevant.

> Also, this proposal only improves the sourcing of the UTXO set. Currently this
> needs to happen through some third party source and loaded into the node
> manually which comes with it’s own set of potential risks (privacy, malware),
> being able to rely on the P2P network as a secure source is preferable to that.

This is again an implementation detail of a specific node. Neither assumevalid nor assumeutxo are protocol. These are trust-based features of a specific node implementation (not a "secure source"). The distribution of trusted blobs was a known design flaw of assumeutxo. But it has long been suggested that these could be just distributed via the p2p network. The similar bip64 was in 2014. Predictably the former is now being used to justify the latter. But of course this presents another problem, that of the cost of validating them, requiring full validation of the chain. So this inevitably leads to miner commitments.

> I think your main critique boils down to “this is a slippery slope” aside from
> your critique of assumeutxo... I can not refute
> critique of something that is not part of this proposal except for pointing out
> that what you are insinuating is not something I am working on or plan on
> working on...

Even if for some reason you cannot comment, I and others can. The above slide from trusted utxo downloads to p2p distribution of them makes the point already. Ad-hoc downloads was obviously going to lead to the p2p distribution proposal. And that proposal (here) is obviously going to lead to a new proposal for miner commitments to utxo state. This has been discussed as far back as 2015, and has been implemented in altcoins. It was a primary big-blocker proposal to resolve the inability to validate larger blocks. It achieves this by not validating them, which is of course the critique. Whether you would support that or not is not the relevant question.

> In contrast to some hypothetical dangerous future extension of this
> proposal that you are warning about...

It is not hypothetical, and it is dangerous. This understanding is at least 11 years old:

>> Full nodes using UTXO set commitments is a change to the bitcoin
>> security model.
>>
>> Currently an attacker with >50% of the network hashrate can rewrite history.
>>
>> If full nodes rely on UTXO set commitments such an attacker could create
>> an infinite number of bitcoins (as in many times more than the current
>> 21 million bitcoin limit).
>>
>> Before we consider mechanisms for UTXO set commitments, we should
>> seriously discuss whether the security model reduction is reasonable.

- Patrick Strateman, 2015

https://gnusha.org/pi/bitcoindev/55FC6951...@gmail.com/

> I am convinced that it does have real positive impact on users
> today, as I pointed out above.

Entirely dismissing these very relevant issues while assuming a "real positive impact" is not sound analysis. I am not aware of any use of a not validated full node. Maybe an untrusted block explorer, but there are plenty of those available online. Some full nodes do provide full functionality up to the point of validation, while building the chain (including block explorers).

This proposal is a bug (p2p trusted distribution) that attempts to fix the assumeutxo bug (ad-hoc trusted distribution), and the only "fix" to the latter will be miner commitments (soft fork). And there is no material benefit to any of it. The chain must still be fully validated, and is not usable until it is. Arguments in favor of this approach are thinly veiled support for a rolling utxo commitment scheme, as a "solution" to the lack of scalable implementation.

e


Reply all
Reply to author
Forward
0 new messages