From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Thu, 07 May 2026 15:09:23 -0700 Received: from mail-yx1-f56.google.com ([74.125.224.56]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wL6uH-0001rn-BC for bitcoindev@gnusha.org; Thu, 07 May 2026 15:09:23 -0700 Received: by mail-yx1-f56.google.com with SMTP id 956f58d0204a3-649deef077esf2284244d50.1 for ; Thu, 07 May 2026 15:09:21 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1778191755; cv=pass; d=google.com; s=arc-20240605; b=HomJtczp2a3D2gTpi8Woro8QVSIxHEPToYQSGI5S3ybyCS96ufx86fm38HBM7gRWRv OYECtek6jT+SG8ip1xHjctPYzvqCOpOLqABB505RSWhB+7cTMqcR+N5wZeN4Oiu+SAVF Q1Pf5u3BemEdZWrb4W8e92w2nfNHtaauU9buI3H/lf3xi6rFK3YMrAc/jEuWYC4YUxXu sIwqiKDXLF5/pgSUgEhmGK1pggykbxd+qbKRJHLS+j92cvYMN6mzBqcVhrgXt5HL4q/Q Pe6vweqHJ32Xr6wAAnxaNuB+e1k4a4i30mQ4nm8np9M25U3WUumxz/NO3xzeI6d9JEcu F9jw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:mime-version:feedback-id :references:in-reply-to:message-id:subject:cc:from:to:date :dkim-signature; bh=RN6Q0WWg6E6yn4hsZsziAoWV/ksAlY3ZU4+d288QSPM=; fh=8Sdj+glvHliWozPkj1BEN7CVm7Fa37RGbXEUZkIgkyY=; b=HSkunlnfMZLuezYOFu6c1FvUpNLoBIdSv316elr6Tda+fwnbwMiLECLuVQnRcku5KD Kp6O9BBb19e0Rv2NtYexYK7Wo33JCQONx1rZpqJkeA/+ua7p8Am/NsAjIzt1c2Fs6qcG GhISYiXBBp6DL4RErwqSgTEOrCJaIxcZReEXaHLIhXy+SQKwCKZ8K9qnxWVVfjNUaEGf vu6AR/2t7WyYVNJhBLAY4cxUlXjQvm8TeePdNTgC49kM3UYR3W9ZoArLtLv+Gr6WOdBN s9FaSox5JjO+E5sEjiPXsSi3m2NC0GDqT2kdQqnKVnsOpssx0MuEEz/0t5jBT136v1gd ctIg==; darn=gnusha.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=cisDltx7; spf=pass (google.com: domain of fjahr@protonmail.com designates 79.135.106.29 as permitted sender) smtp.mailfrom=fjahr@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20251104; t=1778191755; x=1778796555; darn=gnusha.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :date:from:to:cc:subject:date:message-id:reply-to; bh=RN6Q0WWg6E6yn4hsZsziAoWV/ksAlY3ZU4+d288QSPM=; b=l+CVgtQPvVdL+ouhUksMH8vuCL6d6x03L2FP0NEg3JaU0Hu9lunf/elGfkeXT04uOi mCKKmhWfyoaBIBCBD2vP549efbs6FEbslYAjl3wx8aTyy6qF/7/8om5z46P/bcAyJG2l 9uY/FLxPH2NUUW8KRHyOoz8T1mIKwI5C1qRa3Z8zCdSbgDzlwG6df2noox9kMeih/1jU 60srkkyFSRYqksgNnW7Tg3g1tct5Z9cuHIvvQmkS76TIBF+866CfNEXVXMQOGGnnplHY 7wIivprES2662apUaOKJBQJcIC9VMjl+GokDv+rGl15wZ6eQtHLmagmIQ744BVV4d0Es IeyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778191755; x=1778796555; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :date:x-beenthere:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=RN6Q0WWg6E6yn4hsZsziAoWV/ksAlY3ZU4+d288QSPM=; b=UdaSZETQRgZzwD8Q1qcW4BWpE6Gx0Vp+A4IzUJDsWycK/bkc4oECYUYuBJzkOQT0HH OidMfRt0+Fd87ilavBd3FijbEZkcp4c7UYR5V1iy4XKBLvv8lWAwjX292Uomyr/59WoT 5AWx/zVhFihULvxrM4L/HRU3aCSgVIQcgw/k6p1XrR1Dogacvluj4jQLJp9XPgkEVg4n vJTcrkjFnoW124PSmrtLN/oyG1zRVMnzpAHyIsJs5+K84m23d0zdpwTSHPFIQyruh3yf CdsjD+un6QnoHmhYVtLR8HxFJVaxuadncy7DLr0M0CpIlMlnfd858SCT1fE1Ms+oncc6 hzKw== X-Forwarded-Encrypted: i=2; AFNElJ/39PQY4x77+bb2o9oakcT9xTcfYP/dDF6BAnkqkCfzT0RFeT0FfhS1caI+CRCN6IT5SWhFp90QTYXY@gnusha.org X-Gm-Message-State: AOJu0Yyn0f9s31t375C9EFGb2FGb7Tw60Wxc2vvCXldJVDCjd/kaJjPH IHX8nj6sGDPrD7lBYADYFNz1K9RfqFew7Nw8GTLH5cBUdHe4bYdB4xQw X-Received: by 2002:a05:690e:4410:b0:650:11b3:3f4e with SMTP id 956f58d0204a3-65c79d94d3dmr7751637d50.32.1778191754969; Thu, 07 May 2026 15:09:14 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AUV6zMPYMgcgk5QRwFByJTsK8HG42jFYmCdjkq2s9jOe+Umt8Q==" Received: by 2002:a53:c58c:0:b0:650:696e:fd3c with SMTP id 956f58d0204a3-65d7cfb3ef5ls1569893d50.3.-pod-prod-07-us; Thu, 07 May 2026 15:09:09 -0700 (PDT) X-Received: by 2002:a05:690c:399:b0:7bd:9f34:59a3 with SMTP id 00721157ae682-7bdf5debfdemr108074227b3.11.1778191749576; Thu, 07 May 2026 15:09:09 -0700 (PDT) Received: by 2002:ab3:7d18:0:b0:2f6:91ae:47ef with SMTP id a1c4a302cd1d6-2ff58c8315amsc7a; Thu, 7 May 2026 14:50:07 -0700 (PDT) X-Received: by 2002:a05:6512:3b86:b0:5a8:6f10:799c with SMTP id 2adb3069b0e04-5a887cde92amr3497881e87.21.1778190605725; Thu, 07 May 2026 14:50:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778190605; cv=none; d=google.com; s=arc-20240605; b=konTLJkrOEvsOJ5HVztWQOJr+lPJqPllR1ZYGRLHao7npZbUf7+WNefIHw4khhFcgW mFWIMU7qcGwCO6raFEUttlUx2QMRTekrrEA3lNRAPCOe2tVBsDBRxchYuE+Y4wU7s4mj NsDR7ex7NV2Oz4iFKFq/cdDVsBAmkf4V1Dv5lg3OHrjoxnkqZEqtG17oaQ7t2HzKz29C u2D4kSHXqySsgtwYNhoaNPpyRQ2sxH4lufu0ujy+pE7ILt8z9ZhuLVToDTOuNY7XJPUi CjL6ZQqFy+/UBvRbUhgImwE5pdDQLM3wfo27DQrJaiHkv9MELCqd4Ft4MjSEyR+FwFzr eNJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=mime-version:feedback-id:references:in-reply-to:message-id:subject :cc:from:to:date:dkim-signature; bh=K7Gtn87UAG22ibVg+z5yHxEqSar2fwzheHPiRH+WnQo=; fh=sapDHqhE46zLmMBeB1lkoe0zq8J9+V3Afx71/j8kvug=; b=LxtH94FkMQYv06X5rD5NzINmwY8PGsBtH8oSlzE8WgJxkrkaEz4l+tP76eYC+9SRcz HnOQ92VpOGHuVxzo35RhsfTKJnwP7A31jKH8OfbzVymX6B+1jOPDABpBwHHgOXxZxG7R dwR5ndLkkMFmlYuLyvfTmgiCtfofm4aqo3m1Da+FsXl9NwT9fXQDiDMMIqsYwo+0MXQL 3EfAkNm42INSqRYwwXqLKx+iai6yo2QYYgg0o6Fd9ZIg2tY9rdL2/6wem6avaTcZ3MeI UsThJaiOZ2+0U8IxbpVxJu3Cbvud/8mdBdAnbo7f81KoCWujvXTA9Mf5i3GZCEIRWDxx oBGw==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=cisDltx7; spf=pass (google.com: domain of fjahr@protonmail.com designates 79.135.106.29 as permitted sender) smtp.mailfrom=fjahr@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: from mail-10629.protonmail.ch (mail-10629.protonmail.ch. [79.135.106.29]) by gmr-mx.google.com with ESMTPS id 2adb3069b0e04-5a8a42f68a0si11305e87.2.2026.05.07.14.50.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 May 2026 14:50:05 -0700 (PDT) Received-SPF: pass (google.com: domain of fjahr@protonmail.com designates 79.135.106.29 as permitted sender) client-ip=79.135.106.29; Date: Thu, 07 May 2026 21:50:00 +0000 To: Antoine Riard From: "'Fabian' via Bitcoin Development Mailing List" Cc: Bitcoin Development Mailing List Subject: Re: [bitcoindev] Re: [BIP Draft] P2P UTXO Set Sharing Message-ID: In-Reply-To: References: <19616822-8a03-4de1-99be-72d50479208fn@googlegroups.com> Feedback-ID: 5067558:user:proton X-Pm-Message-ID: 13dc5cbd365d2cd6412949412a4a305eb9061aef MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="b1=_qyIm4lWUi9pSWxwMqqrSvCrRnJ44cu2qFFI8go4Hoc" X-Original-Sender: fjahr@protonmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=cisDltx7; spf=pass (google.com: domain of fjahr@protonmail.com designates 79.135.106.29 as permitted sender) smtp.mailfrom=fjahr@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com X-Original-From: Fabian Reply-To: Fabian Precedence: list Mailing-list: list bitcoindev@googlegroups.com; contact bitcoindev+owners@googlegroups.com List-ID: X-Google-Group-Id: 786775582512 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Score: -1.0 (-) --b1=_qyIm4lWUi9pSWxwMqqrSvCrRnJ44cu2qFFI8go4Hoc Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Antoine, thanks for your feedback. The idea to use BIP434 is indeed very tempting. I had lost track of that pr= oposal 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 Bitcoi= n Core PR before I make a final decision on moving the proposal over, but m= y feeling right now is that this is likely to happen unless I am overlookin= g any roadblocks. I am not sure I can follow your point on the computational worst case. If t= he 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 t= o the peer. I also can't really grasp the BIP157 scheme to help with this b= ut 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 On Wednesday, May 6th, 2026 at 3:28 AM, Antoine Riard wrote: > Hello Fabian, From a short read over the BIP, I'm wondering if the presen= t BIP proposal wouldn't be better implemented as a feature on top of the BI= P 434 (and that would be an opportunity to exercise the proposed mechanism)= . Keeping reserved a service bit means implementation that don't wish to su= pport 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 pa= rsing and validation of the `utxotree`. What if the forwarding peer is an a= sshole and share you a crappy utxo set, where validity will be only asserte= d when you received and verify the latest utxo with the latest `utxoset`. T= here 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 recip= ient. 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 c= lient-server like flow (independently of the consideration that one find as= sume-utxo interesting as a validation model). Best, Antoine OTS hash: ba583= 724bad6f5251fd793abf626a598f64a1dcd9f5ff6b1f91e1cbd02c09774 > > Le Tuesday, May 5, 2026 =C3=A0 5:17:53=E2=80=AFPM UTC+1, Eric Voskuil a = =C3=A9crit : > >> Concept NACK. It's bad enough that nodes are formalizing this off networ= k, but incorporating it into p2p is another level of awful. >> >> On Tuesday, May 5, 2026 at 11:39:56=E2=80=AFAM UTC-4 Fabian wrote: >> >>> 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/bitcoi= n/bips/pull/2137 >>> >>> Fabian >>> >>> ``` >>> BIP: ? >>> Layer: Peer Services >>> Title: P2P UTXO Set Sharing >>> Authors: Fabian Jahr >>> 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 be= tween 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 th= e requesting node, enabling >>> per-chunk verification. This allows nodes to bootstrap from a recent he= ight 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 be= gin operating from a serialized >>> UTXO set while validating >>> historical blocks in the background. However, there is currently no can= onical source for obtaining this >>> data. Users must either generate one themselves from a fully synced nod= e (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 a= vailable to serve. >>> A node signaling `NODE_UTXO_SET` MUST be capable of responding to `getu= txotree` 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=E2=80=939 | Number of outputs for th= is txid. | >>> >>> For each coin in the group: >>> >>> | Field | Type | Size | Description | >>> |-------|------|------|-------------| >>> | `vout_index` | `compact_size` | 1=E2=80=939 | 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 buil= t as a balanced binary tree. When >>> the number of nodes at a level is odd, the last node is duplicated befo= re 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 b= y recomputing the root and >>> comparing. The Merkle root is the sole trust input required to verify t= he integrity of the received UTXO set. >>> >>> `SHA256d` denotes double-SHA256: `SHA256d(x) =3D 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 se= t. | >>> | `data_length` | `uint64_t` | 8 | Total size of the serialized UTXO se= t in bytes (header + body). | >>> | `num_chunks` | `compact_size` | 1=E2=80=939 | Number of chunks the se= rialized UTXO set is split into. | >>> | `chunk_hashes` | `uint256[]` | 32 =C3=97 `num_chunks` | The ordered l= ist 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 dis= connect the peer. >>> >>> #### `getutxoset` >>> >>> Sent to request a single chunk of UTXO set data. The requesting node MU= ST 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 ch= unk. | >>> >>> If the serving node cannot fulfill the request, it MUST NOT respond. Th= e 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 fo= r the last chunk. | >>> >>> The transfer is receiver-driven: the requesting node sends one `getutxo= set` 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 UT= XO 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`, `bloc= k_hash`) that do not match >>> the outstanding request. >>> >>> After all chunks have been received, the node SHOULD parse the reassemb= led 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 t= o 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` exch= anges, verifying each chunk >>> against its entry in the accepted `utxotree` on receipt. On verificatio= n failure the peer is >>> disconnected and download continues from another peer without losing al= ready-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 t= ransfers per peer at their own >>> discretion to manage resource consumption. >>> >>> ## Rationale >>> >>> **Usage of service bit 12:** Service bits allow selective peer discover= y through >>> DNS seeds and addr relay. Bit 12 is chosen as the next unassigned bit a= fter `NODE_P2P_V2` (bit 11, BIP 324). >>> >>> **Direct request model:** Peers signal availability of UTXO sets via th= e `NODE_UTXO_SET` >>> service bit; the requesting node identifies the desired UTXO set by blo= ck hash when sending >>> `getutxotree`. The serving node responds only if it can serve that spec= ific 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 imme= diate detection of corrupt data, >>> peer switching without data loss, and parallel download from multiple p= eers. 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 ~1= 0 GB set) against memory usage >>> for buffering and verifying a single chunk. Smaller chunks would increa= se protocol overhead; larger >>> chunks would increase memory pressure on constrained devices commonly u= sed to run Bitcoin nodes. >>> Together with the additional message overhead, the `utxoset` message in= cluding the chunk data also >>> sits just below the theoretical maximum block size which means any impl= ementation should be able to >>> handle messages of this size. >>> >>> **Reusing the `dumptxoutset` format:** Avoids introducing a new seriali= zation format and ensures >>> compatibility with UTXO sets already being generated and shared. >>> >>> **Relationship to BIP 64:** BIP 64 defined a protocol for querying indi= vidual UTXOs by outpoint and is >>> now closed. This BIP addresses a different use case: bulk transfer of t= he entire UTXO set for node >>> bootstrapping. >>> >>> ## Reference Implementation >>> >>> [Bitcoin Core implementation pull request](https://github.com/bitcoin/b= itcoin/pull/35054) >>> >>> ## Copyright >>> >>> This BIP is made available under the terms of the 2-clause BSD license.= See >>> https://opensource.org/license/BSD-2-Clause for more information. >>> >>> ## 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 sol= e integrity check >>> * __0.1.0__ (2026-04-10): * Initial draft > > -- > 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+unsubscribe@googlegroups.com. > To view this discussion visit https://groups.google.com/d/msgid/bitcoinde= v/aa597737-e07e-4809-82bf-6226080db418n%40googlegroups.com. --=20 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 e= mail to bitcoindev+unsubscribe@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/= oxOhrPdtSrVJyOSa6swJOf_2PHG7Qa-wILXijPwV4I7csTWjNU6veB9cBKvWmDknqartB2zouY5= jDtS4dnx-qFGAKvypXlje4WL_MB5QO0U%3D%40protonmail.com. --b1=_qyIm4lWUi9pSWxwMqqrSvCrRnJ44cu2qFFI8go4Hoc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Antoine,=

<= /div>
thanks= for your feedback.

The idea to use BIP434 is indeed very tempting. I had lost tra= ck 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 Bi= tcoin Core PR open for it. I will look over BIP434 again in detail and revi= ew the Bitcoin Core PR before I make a final decision on moving the proposa= l 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 comput= ational worst case. If the node has the root of the Merkle tree of chunks e= mbedded AssumeUTXO style or if it knows the root from somewhere else it wil= l get an actual UTXO set. So I don't understand how the "crappy utxo set" w= ould look like and get to the peer. I also can't really grasp the BIP157 sc= heme to help with this but that's probably because I am not understanding t= he issue to begin with. If you could give me a bit more details and/or a co= ncrete example here that would be really great!

Thanks,
Fabian
On Wednesday, May 6th, 2026 at 3:28 AM, Antoine Riard <antoine.r= iard@gmail.com> wrote:
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 reserv= ed a service bit means implementation that don't wish to support the feature d= on'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 i= s an asshole and share you a crappy utxo set, where validity will be only ass= erted when you received and verify the latest utxo with the latest `utxoset`. The= re could be an intermediary "authentication" step a la BIP157 of the root itse= lf, if you're peers assume-utxo servicing discovery is sane and you're connecte= d 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<= /span>

Le Tuesday, May 5, 2026 =C3=A0 5:17:53=E2=80=AFPM UTC+1, Eric Voskuil = a =C3=A9crit :
Concept NACK. It's bad enough that nodes are formalizing this off network,= but incorporating it into p2p is another level of awful.

On Tuesday, May 5, = 2026 at 11:39:56=E2=80=AFAM UTC-4 Fabian wrote:
Dear list,

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

Fabian


```
BIP: ?
Layer: Peer S= ervices
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 servic= e bit `NODE_UTXO_SET`, four new P2P messages (`getutxotree`, `utxotree`, `g= etutxoset`,
`utxoset`), and a chunk-hash list anchor= ed 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 oper= ating from a serialized
UTXO set while validating
historical blocks in the background. However, there is= currently no canonical source for obtaining this
da= ta. Users must either generate one themselves from a fully synced node (usi= ng `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 f= rom
peers, removing the dependency on external infra= structure.

## Specification

The key words "MUST", "MUST NOT", "SHOULD", "S= HOULD NOT", and "MAY" in this document are to be
int= erpreted as described in RFC 2119.

##= # Service Bit

| Name | Bit | Descript= ion |
|------|-----|-------------|
= | `NODE_UTXO_SET` | 12 (0x1000) | The node can serve complete UTXO se= t data for at least one height. |

A n= ode MUST NOT set this bit unless it has at least one full UTXO set availabl= e to serve.
A node signaling `NODE_UTXO_SET` MUST be= capable of responding to `getutxotree` and `getutxoset`
<= span>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

<= span>The serialized UTXO set uses the format established by the Bitcoin Cor= e RPC `dumptxoutset` (as of Bitcoin Core v31).

<= div>**Header (55 bytes):**

| Fi= eld | Type | Size | Description |
|-------|------|--= ----|-------------|
| `magic` | `bytes` | 5 | `0x757= 4786fff` (ASCII `utxo` + `0xff`). |
| `version` | `u= int16_t` | 2 | Format version. |
| `network_magic` |= `bytes` | 4 | Network message start bytes. |
| `bas= e_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 tr= ansaction hash. For each group:

| Fie= ld | Type | Size | Description |
|-------|------|---= ---|-------------|
| `txid` | `uint256` | 32 | Trans= action hash. |
| `num_coins` | `compact_size` | 1=E2= =80=939 | Number of outputs for this txid. |

For each coin in the group:

|= Field | Type | Size | Description |
|-------|------= |------|-------------|
| `vout_index` | `compact_siz= e` | 1=E2=80=939 | Output index. |
| `coin` | `Coin`= | variable | Serialized coin (varint-encoded code for height/coinbase, the= n compressed txout). |

Coins are orde= red lexicographically by outpoint (txid, then vout index), matching the Lev= elDB iteration
order of the coins database.

#### Chunk Merkle Tree

<= /div>
The serialized UTXO set (header + body) is split into chunk= s of exactly 3,900,000 bytes (3.9 MB). The
last chun= k contains the remaining bytes and may be smaller.

The leaf hash for each chunk is `SHA256d(chunk_data)`. The tr= ee is built as a balanced binary tree. When
the numb= er of nodes at a level is odd, the last node is duplicated before hashing t= he next level.
Interior nodes are computed as `SHA25= 6d(left_child || right_child)`.

The l= eaves are delivered to the node in a single `utxotree` response. A node tha= t 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) =3D SHA256(SHA256(x))`.=

### Messages

#### `getutxotree`

Sent to re= quest 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 reasonab= le timeout and try another peer.

####= `utxotree`

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

| Field |= Type | Size | Description |
|-------|------|------|= -------------|
| `block_hash` | `uint256` | 32 | Blo= ck hash this data corresponds to. |
| `version` | `u= int16_t` | 2 | Format version of the serialized UTXO set. |
| `data_length` | `uint64_t` | 8 | Total size of the serialized UTX= O set in bytes (header + body). |
| `num_chunks` | `= compact_size` | 1=E2=80=939 | Number of chunks the serialized UTXO set is s= plit into. |
| `chunk_hashes` | `uint256[]` | 32 =C3= =97 `num_chunks` | The ordered list of chunk hashes. |
Upon receiving a `utxotree` message, the node MUST recomp= ute 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 respon= se and MUST disconnect the peer.

####= `getutxoset`

Sent to request a singl= e chunk of UTXO set data. The requesting node MUST have received a `utxotre= e`
for the corresponding UTXO set before sending thi= s message.

| Field | Type | Size | De= scription |
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash identifyi= ng the requested UTXO set. |
| `chunk_index` | `uint= 32_t` | 4 | Zero-based index of the requested chunk. |
If the serving node cannot fulfill the request, it MUST N= OT respond. The requesting node SHOULD apply
a reaso= nable timeout and try another peer.

#= ### `utxoset`

Sent in response to `ge= tutxoset`, delivering one chunk.

| Fi= eld | Type | Size | Description |
|-------|------|--= ----|-------------|
| `block_hash` | `uint256` | 32 = | Block hash this data corresponds to. |
| `chunk_in= dex` | `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. Chu= nks MAY be
requested in any order and from different= peers.

Upon receiving a `utxoset` me= ssage, the node MUST compute `SHA256d(data)` and compare it against<= /div>
`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 als= o disconnect
a peer that sends a `utxoset` message w= ith 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 confir= m it is well-formed.

### Protocol Flo= w

1. The requesting node identifies p= eers 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 r= equesting 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 n= ode downloads chunks via `getutxoset`/`utxoset` exchanges, verifying each c= hunk
against its entry in the accepted `utxotree`= on receipt. On verification failure the peer is
= disconnected and download continues from another peer without losing alread= y-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
<= span>discretion to manage resource consumption.

=
## Rationale

**Usage of se= rvice bit 12:** Service bits allow selective peer discovery through<= /div>
DNS seeds and addr relay. Bit 12 is chosen as the next unas= signed bit after `NODE_P2P_V2` (bit 11, BIP 324).

**Direct request model:** Peers signal availability of UTXO se= ts via the `NODE_UTXO_SET`
service bit; the requesti= ng node identifies the desired UTXO set by block hash when sending
`getutxotree`. The serving node responds only if it can serv= e that specific UTXO set.

**Per-chunk= verification:** The chunk-hash list returned in `utxotree` enables each ch= unk to be verified
by direct lookup against the acce= pted 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 K= B for a ~10 GB set). The specified serialization is deterministic, so all h= onest nodes produce
byte-identical output, guarantee= ing Merkle root agreement.

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

**Re= using the `dumptxoutset` format:** Avoids introducing a new serialization f= ormat and ensures
compatibility with UTXO sets alrea= dy being generated and shared.

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

## Re= ference 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 befo= re download approach, instead request the chunk-hash list via `getutxotree`= /`utxotree`
* Dropped per-chunk Merkle proofs; c= hunks 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 ch= eck
* __0.1.0__ (2026-04-10):
= * Initial draft

--
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 e= mail to bitcoindev+u= nsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/aa597737-e07e-4809-82b= f-6226080db418n%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups &= quot;Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to bitcoind= ev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/= oxOhrPdtSrVJyOSa6swJOf_2PHG7Qa-wILXijPwV4I7csTWjNU6veB9cBKvWmDknqartB2zouY5= jDtS4dnx-qFGAKvypXlje4WL_MB5QO0U%3D%40protonmail.com.
--b1=_qyIm4lWUi9pSWxwMqqrSvCrRnJ44cu2qFFI8go4Hoc--