From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Fri, 22 May 2026 06:47:18 -0700 Received: from mail-oo1-f55.google.com ([209.85.161.55]) by mail.fairlystable.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1wQQDc-0008HC-JZ for bitcoindev@gnusha.org; Fri, 22 May 2026 06:47:18 -0700 Received: by mail-oo1-f55.google.com with SMTP id 006d021491bc7-69d3806d94esf8250242eaf.0 for ; Fri, 22 May 2026 06:47:16 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1779457630; cv=pass; d=google.com; s=arc-20240605; b=YEBrbHsNFqMKR3lEYRYXYzFxccJoeFP5LD6Wb2N0GvnXJaNw4mZSxHfR8msNDO2kLV yefKyfz2Ip6RnZKk2GgxccFPuxi6kvTl8H9edcMPwhIMuLs9M4kph5+90riIpUMryi1e mU+8+07pZ4y3GkIHy/RAyq81KxWDcqmhR4eCkODHHW5fM2YjQxwQJb54n8qgO5OyaHik Awvzju+nV0hyhWsxNo+k9q5nIFpd/VAad+moFpq410cYe8u1fPA3BTqIr0VMXz46FqFh 8RfSAMbcptyCIB1UGxTlqRaPOHxmcDxeCLO/sGxPSCE+a1EcJbBocYL8HeAkbnfM02dx cZrg== 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=rpPqhCxdp6SK3MfP4Oi1e/QtHO2vJ4NPcWZ7rE5piG4=; fh=/FvKFrfibjdvtVaaYZA7h14QNyfxNhKh5d2IP7zQ/0k=; b=adVkcdaou0Bs9kYAVwIFBaGjlsiA/vV7Avd/WXQYnbnpBEGiO6JvcCzlYZJ+Rw9kXu baPFib6xnIcFAykIld3oNBgRZXY8EVvS1+AmTJDfUoENyuOBb7O8m+zbgMfmxp2F3LSH FwHAdkQqO/wn5XXXd2KO5BvolIjRXVPSN7IKtLx+iEdGHEMwK+jo3CW9Mq1N3YAFVMcy O2tRa+w++QMIkJi7IXCqMTPCPS/aFe+fdzGrm/rV8Q6+D7G39xmiuPSgPjsgEgsi7OGa wjcjnkDQ0UlYP0EP3fxxHIrwEJIKGdON+N4W7cISnWffJnfdTMWXmhh1oDxUiqD1BeCJ sVCw==; darn=gnusha.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=bOIA2tyZ; spf=pass (google.com: domain of fjahr@protonmail.com designates 109.224.244.17 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=1779457630; x=1780062430; 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=rpPqhCxdp6SK3MfP4Oi1e/QtHO2vJ4NPcWZ7rE5piG4=; b=xiekgK9yD8MkPg8ju/LoAcBIrcRaxiIQqR5buAxnBg6NmmQhc4Ki1sNWwnBxdFYpKL 9DTVIfq9UOkYwgVid5Vv0oiaQDtldEtjUqzjrWsJnIEUb2oUUzegqCTsVliaLtiERphG rnsCUBQFJDAxgg/5BbpD/U0hc93a6/qO42Zwqs4uiv76x7ic0OBrLrEcOPEXfYlmEwhK 6swC9qOrwkEP7wwKPWzhTtjQlBaLEUqG9AL7pUAXLg+T4d1kB5PRI1LRjVqPI7YYRArp 3Q/dtRC5xjUMCAozCtZvQ45vVNy6uhLSiwPvNt25/Zm23rPSfvV4oX19acvW+4mGMAJl S6gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779457630; x=1780062430; 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=rpPqhCxdp6SK3MfP4Oi1e/QtHO2vJ4NPcWZ7rE5piG4=; b=Z309OFt2/dq+yPOGjs10SP2rvAUqrAJ+zwDbyvk0aEiDe/bJmdO8R4LkM3X6K++Vqq ecvN4PvKbjV9IpZB1bT/QK8CIpy83ICFb3XGIXO7wiAGPJB5OFwX0X9+MY2Dxq9SqZnf XMxDgU+CGfeqBw9kEPEhjRGWy8cl0bOw8HZpC6Hjnoxp4a/5YL5/ZRC9iUHkltKRBIxA I4XdBL3WbAtclmFswwoGgc0puOHXWvxECD3fejSvxkg40iSbid72xfjnlvEJYKQRSPQP DbkN7ZUbpqBI9ju52x2PhI3zuGOId9lK8d2wMJuEOS9Sx4uEOeSede3CoEPA+fEw0dqX 8afQ== X-Forwarded-Encrypted: i=2; AFNElJ+X+Fmuhj6pGfQARYG6UeTGvQSJg7gh//GZd/FxQoZoOgafIdDWbejWOGB9AUQKlNWv20ZUgLXsScqp@gnusha.org X-Gm-Message-State: AOJu0Yx5BSca8f55s1t/HG6BeFrFOnc0uMbu6Sv/lVxtrkr5N6/GnxVo 0JRwywm+50F+3OubR8je1lqjJalYjm4XxJq8QZbG/q8GVk2y/qK7hBl9 X-Received: by 2002:a05:6820:a01:b0:696:7f3d:a75d with SMTP id 006d021491bc7-69d7fdda49bmr1240312eaf.27.1779457630365; Fri, 22 May 2026 06:47:10 -0700 (PDT) X-BeenThere: bitcoindev@googlegroups.com; h="AUV6zMPkVqpebn0uM6YKclphHBfm0p4WTjmAtOIZu3Ut4GTY+g==" Received: by 2002:a05:6870:1606:b0:439:a63f:7165 with SMTP id 586e51a60fabf-43a011ab039ls4120988fac.0.-pod-prod-00-us; Fri, 22 May 2026 06:47:05 -0700 (PDT) X-Received: by 2002:a05:6808:4c09:b0:485:4c40:419d with SMTP id 5614622812f47-4854c40584emr1119546b6e.18.1779457625391; Fri, 22 May 2026 06:47:05 -0700 (PDT) Received: by 2002:a05:6808:5c8:b0:47c:339e:add7 with SMTP id 5614622812f47-4854bbe669fmsb6e; Fri, 22 May 2026 05:52:58 -0700 (PDT) X-Received: by 2002:a17:902:cecc:b0:2b4:5bf8:a7e1 with SMTP id d9443c01a7336-2beb07db515mr30765725ad.6.1779454377081; Fri, 22 May 2026 05:52:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779454377; cv=none; d=google.com; s=arc-20240605; b=HYEP7c2A4+Xg0ePHsmCDspWd7fqc/yYQz1SAvuhv4cHeIEWNgWFGUR2viR6m5DG8s/ RdbVg38KWrL1FYxEHofzDkBRq2PPYBii3NRaT26YXOT1FkcWMiAHZKQjVut7uynpjgJg aeuLveT+IZwWmh8/vNn/gN4wTaw+K1aJ7lk6ZB6kEOBBE/Jo0D32P3Z5HqTNj+2nS6Qe iiNKWOIkpqn44UQl2asFt6qiHhauwC52slaGflMvIOm/8r1A7iZWGvLtUSJzR/5VSbf5 zw1LC3K/RVrUuPsRSrXQYd9BU7MyV/1RaRVAg5lwBOHkAlN1cEZc9k4AiPBNGUdcMZME dPfw== 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=Yhd2gNd6zo3KHEiRu+KSMhz2RQ2mgkMnUSyz0Y2eZh4=; fh=kcu2TuYsAhFPPIH08dMhXO1Q08MxqNa/Ln77l7XY83M=; b=BKNGtJBj/QyI+Ayuu5B1FcNaIZio5lvG+NBnpw4DqEtSeLm8FkLeWytk9iabB5sO7I HJ1dvCrm1WRD/IFkGJp4bx42IzJ2+NNdDJFL+qed+pOA5XcB3iB6D5EykuozGt772zt5 M3VZ8ofL+/bubjUHrlgBNoxMq1GJeAvQklyy89YGPDccxSTsyIXfFxcNTnBGt+asFbuO ypRwyHFDi++Eb2Jg/1t+TLc2RVvw09keDZIxorsut7JarIWZJInBCuQe/LvTLGGf2JTU tnxrilNe9GdesmkhlCYACvPxuBu+09zSkaRNezZ0daBkpj6/PInaIlGFrINtz62qxwwG XuWQ==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=bOIA2tyZ; spf=pass (google.com: domain of fjahr@protonmail.com designates 109.224.244.17 as permitted sender) smtp.mailfrom=fjahr@protonmail.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: from mail-24417.protonmail.ch (mail-24417.protonmail.ch. [109.224.244.17]) by gmr-mx.google.com with ESMTPS id d9443c01a7336-2beb58e009esi468725ad.6.2026.05.22.05.52.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 May 2026 05:52:56 -0700 (PDT) Received-SPF: pass (google.com: domain of fjahr@protonmail.com designates 109.224.244.17 as permitted sender) client-ip=109.224.244.17; Date: Fri, 22 May 2026 12:52:31 +0000 To: josie 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: <8661e699-47d8-46e4-a561-41c5d2fdc0e6n@googlegroups.com> References: <8661e699-47d8-46e4-a561-41c5d2fdc0e6n@googlegroups.com> Feedback-ID: 5067558:user:proton X-Pm-Message-ID: 8b19855d42927c30d21ca452233f2da25c097cce MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="b1=_heqgMggdSIkUos9X69q5od5dZ3Hox1YQJ5N5CI5WyU" 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=bOIA2tyZ; spf=pass (google.com: domain of fjahr@protonmail.com designates 109.224.244.17 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=_heqgMggdSIkUos9X69q5od5dZ3Hox1YQJ5N5CI5WyU Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Josie, on hosting the snapshot on bitcoincore.org: I guess it's fair to say the tr= ust model is the same, but the operational profile really isn't. Hosting th= e files would give a constant attack surface to the process of fetching the= m. At any point the server could be DoS'd, the network layer could be attac= ked (BGP, DNS), admins could be compromised, legal avenues explored to take= down hosting providers or ISP connections, regional reliability issues can= disrupt this and so on. Sure, these are problems that most internet companies face and where soluti= ons exist but these are usually costly and require constant maintenance. Th= e uptime of the bitcoin network has famously been pretty good, per https://= bitcoinuptime.org/. That would be benchmark people would measure this solut= ion by. I am primarily a developer not a server admin so to me this sounds = like a lot more work than maintaining a few hundred lines of code which wou= ld be far from the most complex in any implementation. Best, Fabian On Tuesday, May 19th, 2026 at 2:05 PM, josie wrote: > I think others have articulated legitimate concerns with the AssumeUTXO a= pproach better than I can, so I'll try not to repeat them. > > I'd like to instead take a step back and ask why is this being proposed i= n the first place? Even if I agreed with the AssumeUTXO approach (I do not)= , I would still push back on p2p sharing. AssumeUTXO's trust model is built= around a hash committed to in the Bitcoin Core binary, which the snapshot = is then verified against. So why not just distribute the snapshot from bitc= oincore.org along with the release? As you said, this is meant to be opt-in= so why not keep it fully opt-in by not adding code and attack surface to t= he p2p code that everyone who runs Bitcoin Core will use? > > Furthermore, having the snapshot be distributed by Bitcoin Core makes the= trust model explicitly clear: if you don't trust downloading a snapshot fr= om the Bitcoin Core website then you certainly shouldn't be trusting the ha= sh committed to in the Bitcoin Core binary. This also makes the feature ava= ilable to any user who wants to use it, without requiring a certain number = of peers on the network to also support it. I'd much rather validate before= hand how many people are *actually* using this feature before we continue w= riting more code to support it. > > I'd also like to comment on the bandwidth arguments being used as a justi= fication for AssumeUTXO. This does not make sense to me. Low bandwidth area= s are often on metered bandwidth and AssumeUTXO increases bandwidth usage, = not decreases. Furthermore, if low bandwidth is a concern, has anyone taken= the time to do the math and verify that the node will catch up to the snap= shot in a reasonable amount of time? As a reminder, the node also needs to = keep up with new blocks and transaction relay, which would take away availa= ble bandwidth/CPU from validating in the background. I keep hearing "accept= ing payments" as the use case, which implies to me the node would care a lo= t more about validating recently blocks and learning about transactions. Th= is implies the node may never catch up, or catch up so slowly that it inval= idates the trust model of AssumeUTXO. > > In closing, if I may be a bit (humorous) crass, this feels like putting l= ipstick on a pig by trying to dress up a trusted protocol as less trusted t= han it actually is. > > Cheers, > josie > On Tuesday, May 5, 2026 at 5:39:56=E2=80=AFPM UTC+2 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/bitcoin= /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 bet= ween 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 hei= ght by obtaining the >> required UTXO set directly from the P2P network via mechanisms such as a= ssumeutxo. >> >> ## Motivation >> >> The assumeutxo feature (implemented in Bitcoin Core) allows nodes to beg= in operating from a serialized >> UTXO set while validating >> historical blocks in the background. However, there is currently no cano= nical 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 t= his 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 d= ata for at least one height. | >> >> A node MUST NOT set this bit unless it has at least one full UTXO set av= ailable to serve. >> A node signaling `NODE_UTXO_SET` MUST be capable of responding to `getut= xotree` and `getutxoset` >> requests for every UTXO set it is willing to serve, including the full c= hunk-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 thi= s 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 built= as a balanced binary tree. When >> the number of nodes at a level is odd, the last node is duplicated befor= e 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 th= e 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 U= TXO set. | >> >> A node that has advertised `NODE_UTXO_SET` and can serve the requested U= TXO 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 a= long 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=E2=80=939 | Number of chunks the ser= ialized UTXO set is split into. | >> | `chunk_hashes` | `uint256[]` | 32 =C3=97 `num_chunks` | The ordered li= st 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 c= orresponding UTXO set. If >> the roots do not match, the node MUST discard the response and MUST disc= onnect the peer. >> >> #### `getutxoset` >> >> Sent to request a single chunk of UTXO set data. The requesting node MUS= T 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 U= TXO set. | >> | `chunk_index` | `uint32_t` | 4 | Zero-based index of the requested chu= nk. | >> >> 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 `getutxos= et` 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 UTX= O set. If the hashes do not >> match, the node MUST discard the chunk and MUST disconnect the peer. A n= ode 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 reassembl= ed 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` excha= nges, 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 alr= eady-verified chunks. >> 5. After all chunks are received, the node parses the reassembled UTXO s= et 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 tr= ansfers 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 af= ter `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 bloc= k hash when sending >> `getutxotree`. The serving node responds only if it can serve that speci= fic UTXO set. >> >> **Per-chunk verification:** The chunk-hash list returned in `utxotree` e= nables each chunk to be verified >> by direct lookup against the accepted list as it arrives, allowing immed= iate detection of corrupt data, >> peer switching without data loss, and parallel download from multiple pe= ers. 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 increas= e protocol overhead; larger >> chunks would increase memory pressure on constrained devices commonly us= ed to run Bitcoin nodes. >> Together with the additional message overhead, the `utxoset` message inc= luding the chunk data also >> sits just below the theoretical maximum block size which means any imple= mentation should be able to >> handle messages of this size. >> >> **Reusing the `dumptxoutset` format:** Avoids introducing a new serializ= ation format and ensures >> compatibility with UTXO sets already being generated and shared. >> >> **Relationship to BIP 64:** BIP 64 defined a protocol for querying indiv= idual UTXOs by outpoint and is >> now closed. This BIP addresses a different use case: bulk transfer of th= e entire UTXO set for node >> bootstrapping. >> >> ## Reference Implementation >> >> [Bitcoin Core implementation pull request](https://github.com/bitcoin/bi= tcoin/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 sole= 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/8661e699-47d8-46e4-a561-41c5d2fdc0e6n%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/= KRJNxmvJhInTDgjGdVBPS5kzWXngejQhVHjtuD3jTdPoyAUSGz-dOc3LkuPlA5MAKiVJUGZ5mhA= C-6Orx7AUFwe7Mtm2NBbOQv3x-diwfwM%3D%40protonmail.com. --b1=_heqgMggdSIkUos9X69q5od5dZ3Hox1YQJ5N5CI5WyU Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Josie,

on hosti= ng the snapshot on bitcoincore.org: I guess it's fair to say the trust model is the same, but the operational profile really isn't. Hosting= the files would give a constant attack surface to the process of fetching = them. At any point the server could be DoS'd, the network layer could be at= tacked (BGP, DNS), admins could be compromised, legal avenues explored to t= ake down hosting providers or ISP connections, regional reliability issues = can disrupt this and so on.

Sure, these are problems tha= t most internet companies face and where solutions exist but these are usua= lly costly and require constant maintenance. The uptime of the bitcoin netw= ork has famously been pretty good, per https= ://bitcoinuptime.org/. That would be benchmark people would measure thi= s solution by. I am primarily a developer not a server admin so= to me this sounds like a lot more work than maintaining a few hundred line= s of code which would be far from the most complex in any implementation.
=
Best,
Fabian
On Tuesday, May 19th, 2026 at 2:05 PM, josie <josie@2140.dev>= wrote:
I think others have articulated legitimate concerns with the As= sumeUTXO approach better than I can, so I'll try not to repeat them.
<= br>
I'd like to instead take a step back and ask why is this bein= g proposed in the first place? Even if I agreed with the AssumeUTXO approac= h (I do not), I would still push back on p2p sharing. AssumeUTXO's trust mo= del is built around a hash committed to in the Bitcoin Core binary, which t= he snapshot is then verified against. So why not just distribute the snapsh= ot from bitcoincore.org along with the release? As you said, this is meant = to be opt-in so why not keep it fully opt-in by not adding code and attack = surface to the p2p code that everyone who runs Bitcoin Core will use?
<= br>
Furthermore, having the snapshot be distributed by Bitcoin Co= re makes the trust model explicitly clear: if you don't trust downloading a= snapshot from the Bitcoin Core website then you certainly shouldn't be tru= sting the hash committed to in the Bitcoin Core binary. This also makes the= feature available to any user who wants to use it, without requiring a cer= tain number of peers on the network to also support it. I'd much rather val= idate beforehand how many people are *actually* using this feature before w= e continue writing more code to support it.

= I'd also like to comment on the bandwidth arguments being used as a justifi= cation for AssumeUTXO. This does not make sense to me. Low bandwidth areas = are often on metered bandwidth and AssumeUTXO increases bandwidth usage, no= t decreases. Furthermore, if low bandwidth is a concern, has anyone taken t= he time to do the math and verify that the node will catch up to the snapsh= ot in a reasonable amount of time? As a reminder, the node also needs to ke= ep up with new blocks and transaction relay, which would take away availabl= e bandwidth/CPU from validating in the background. I keep hearing "acceptin= g payments" as the use case, which implies to me the node would care a lot = more about validating recently blocks and learning about transactions. This= implies the node may never catch up, or catch up so slowly that it invalid= ates the trust model of AssumeUTXO.

In closing, if= I may be a bit (humorous) crass, this feels like putting lipstick on a pig= by trying to dress up a trusted protocol as less trusted than it actually = is.

Cheers,
josie
On Tuesday, May 5, 2026 at= 5:39:56=E2=80=AFPM UTC+2 Fabian wrote:
Dear list,

I am sharing a BIP draft for sharing the UTXO set over the P2P netwo= rk, an old idea that makes it possible to utilize AssumeUTXO without sourci= ng a UTXO set dump from a third party source. You can find the full text be= low or comment on the BIPs repository pull directly: https://github.com/bitcoin/bips/pull/2137<= /div>

Fabian


```
BIP: ?
Layer: Peer Servi= ces
Title: P2P UTXO Set Sharing
<= span> Authors: Fabian Jahr <fj...@protonm= ail.com>
Status: Draft
Type: Specification
Assigned: ?
<= div> Discussion: ?
Version: 0.2.0
License: BSD-2-Clause
```

## Abstract

This BIP defines a P2P protocol extension for sharing full UTXO sets bet= ween peers. It introduces
a new service bit `NODE_UT= XO_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-chu= nk verification. This allows nodes to bootstrap from a recent height by obt= aining the
required UTXO set directly from the P2P n= etwork via mechanisms such as assumeutxo.

<= span>## Motivation

The assumeutxo fea= ture (implemented in Bitcoin Core) allows nodes to begin operating from a s= erialized
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 `dumptxouts= et` in
Bitcoin Core), or download one from a third = party.

By enabling UTXO set sharing o= ver 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", an= d "MAY" in this document are to be
interpreted as de= scribed in RFC 2119.

### Service Bit<= /span>

| 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 s= et this bit unless it has at least one full UTXO set available to serve.
A node signaling `NODE_UTXO_SET` MUST be capable of re= sponding to `getutxotree` and `getutxoset`
requests = for every UTXO set it is willing to serve, including the full chunk-hash li= st and every
chunk of those sets.
<= br>
### Data Structures

#### Serialized UTXO Set

The seria= lized UTXO set uses the format established by the Bitcoin Core RPC `dumptxo= utset` (as of Bitcoin Core v31).

**He= ader (55 bytes):**

| Field | Type | S= ize | Description |
|-------|------|------|---------= ----|
| `magic` | `bytes` | 5 | `0x7574786fff` (ASCI= I `utxo` + `0xff`). |
| `version` | `uint16_t` | 2 |= Format version. |
| `network_magic` | `bytes` | 4 |= Network message start bytes. |
| `base_height` | `u= int32_t` | 4 | Block height of the UTXO set. |
| `ba= se_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):**<= /span>

Coins are grouped by transaction hash= . For each group:

| Field | Type | Si= ze | Description |
|-------|------|------|----------= ---|
| `txid` | `uint256` | 32 | Transaction hash. |=
| `num_coins` | `compact_size` | 1=E2=80=939 | Numb= er of outputs for this txid. |

For ea= ch 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 lexicogr= aphically by outpoint (txid, then vout index), matching the LevelDB iterati= on
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 t= he 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 leve= l.
Interior nodes are computed as `SHA256d(left_chil= d || right_child)`.

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

`SHA256d` de= notes double-SHA256: `SHA256d(x) =3D SHA256(SHA256(x))`.
<= br>
### Messages

####= `getutxotree`

Sent to request the ch= unk-hash list for a specific UTXO set.

| Field | Type | Size | Description |
|-------|---= ---|------|-------------|
| `block_hash` | `uint256`= | 32 | Block hash identifying the requested UTXO set. |
<= br>
A node that has advertised `NODE_UTXO_SET` and can serv= e 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 a= nd try another peer.

#### `utxotree`<= /span>

Sent in response to `getutxotree`, de= livering 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. |
| `d= ata_length` | `uint64_t` | 8 | Total size of the serialized UTXO set in byt= es (header + body). |
| `num_chunks` | `compact_size= ` | 1=E2=80=939 | Number of chunks the serialized UTXO set is split into. |=
| `chunk_hashes` | `uint256[]` | 32 =C3=97 `num_chu= nks` | The ordered list of chunk hashes. |

= Upon receiving a `utxotree` message, the node MUST recompute the Merk= le root from
`chunk_hashes` and compare it against t= he 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 U= TXO set data. The requesting node MUST have received a `utxotree`
for the corresponding UTXO set before sending this message.

| Field | Type | Size | Description |<= /span>
|-------|------|------|-------------|
| `block_hash` | `uint256` | 32 | Block hash identifying the reque= sted 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 timeou= t and try another peer.

#### `utxoset= `

Sent in response to `getutxoset`, d= elivering one chunk.

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

The transfer is receiver-dr= iven: 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 n= ode 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 di= scard 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 o= utstanding 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 adverti= sing `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 no= de verifies the response by recomputing
the Merkl= e root against a value it knows for the given UTXO set, either from a trust= ed source
or by selecting a root with agreement a= mong multiple peers.
4. The requesting node download= s chunks via `getutxoset`/`utxoset` exchanges, verifying each chunk<= /div>
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 c= hunks.
5. After all chunks are received, the node pa= rses 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
discret= ion 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 a= fter `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 iden= tifies the desired UTXO set by block hash when sending
`getutxotree`. The serving node responds only if it can serve that speci= fic UTXO set.

**Per-chunk verificatio= n:** The chunk-hash list returned in `utxotree` enables each chunk to be ve= rified
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 multipl= e 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 r= oot agreement.

**3.9 MB chunk size:**= The number balances round trips (~2,560 for a ~10 GB set) against memory u= sage
for buffering and verifying a single chunk. Sma= ller 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 me= ssages of this size.

**Reusing the `d= umptxoutset` format:** Avoids introducing a new serialization format and en= sures
compatibility with UTXO sets already being gen= erated and shared.

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

## Reference Impl= ementation

[Bitcoin Core implementati= on pull request](https://gith= ub.com/bitcoin/bitcoin/pull/35054)

## Copyright

This BIP is made avail= able under the terms of the 2-clause BSD license. See

## Changelog

* __0.2.0__ (2026-05-0= 4):
* Dropped discovery before download approach= , instead request the chunk-hash list via `getutxotree`/`utxotree`
* Dropped per-chunk Merkle proofs; chunks verified direc= tly against the chunk-hash list
* Dropped `heigh= t` from requests (`block_hash` is the sole identifier); added format `versi= on` to `utxotree`
* Dropped references to the se= rialized hash; the Merkle root is the sole 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 e= mail to bitcoindev+u= nsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/8661e699-47d8-46e4-a56= 1-41c5d2fdc0e6n%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/= KRJNxmvJhInTDgjGdVBPS5kzWXngejQhVHjtuD3jTdPoyAUSGz-dOc3LkuPlA5MAKiVJUGZ5mhA= C-6Orx7AUFwe7Mtm2NBbOQv3x-diwfwM%3D%40protonmail.com.
--b1=_heqgMggdSIkUos9X69q5od5dZ3Hox1YQJ5N5CI5WyU--