SwiftSync is a protocol for clients to parallelize initial block download, based on the original writeup.
BIPs 455–457: SwiftSync Specification #2152
pull rustaceanrob wants to merge 3 commits into bitcoin:master from rustaceanrob:swiftsync-bips changing 7 files +673 −0-
rustaceanrob commented at 12:00 PM on May 6, 2026: member
-
in bip-xxxx-swiftsync.md:9 in 4bb9e9ed4a outdated
0 | @@ -0,0 +1,86 @@ 1 | +``` 2 | + BIP: ? 3 | + Layer: Applications 4 | + Title: SwiftSync initial block download 5 | + Authors: Robert Netzke <bips@2140.dev>, Ruben Somsen <bips@2140.dev> 6 | + Status: Draft 7 | + Type: Specification 8 | + Assigned: ? 9 | + License: BSD-3-Clause
murchandamus commented at 12:36 PM on May 6, 2026:Could you please add links to the relevant discussions on the mailing list and Delving on this document and the others?
License: BSD-3-Clause Discussion: https://groups.google.com/g/bitcoindev/c/FpSWUxItXQs/m/pnfjP6rFCgAJin bip-xxxx-swiftsync.md:12 in 4bb9e9ed4a
7 | + Type: Specification 8 | + Assigned: ? 9 | + License: BSD-3-Clause 10 | + Requires: BIP ?, BIP ? 11 | +``` 12 | +# Abstract
murchandamus commented at 12:37 PM on May 6, 2026:IIRC, Markdown only allows a single first-level header per document, so you probably want to bump all of the headers up one level.
## Abstractmurchandamus commented at 12:37 PM on May 6, 2026: memberJust a quick first glance, but could you please break your text into shorter lines? That makes it easier to leave review and track what changed between commits. Either 100 or 120 characters per line seems to work well enough.
murchandamus added the label New BIP on May 6, 2026murchandamus added the label PR Author action required on May 6, 2026in bip-xxxx-block-undo.md:16 in 2d75492110
11 | +``` 12 | + 13 | +# Abstract 14 | + 15 | +Inputs of a Bitcoin block are referenced by the outpoint data structure. This poses a limitation during initial block download (IBD), such that a client must process blocks sequentially to validate the chain history. The SwiftSync protocol allows blocks to be evaluated in arbitrary order, however additional data is required that must be served over the peer-to-peer network. Namely, the creation height, coinbase flag, input script, and amount for each spent coin must be accessible to fully validate a block in a state-less manner. This data cannot be trusted by a peer under usual conditions, however SwiftSync allows a client performing IBD to validate the correctness of this data. 16 | +# Motivation
danielabrozzoni commented at 12:50 PM on May 6, 2026:The motivation is a bit repetitive with what's in the abstract, and there are a lot of technical details. I would reshape this a little in order to give a stronger motivation ("IBD is slow because it must be done sequentially, SwiftSync speeds this up by removing this limitation")
jurraca commented at 12:57 PM on May 8, 2026:The Abstract and Motivation repeat similar ideas. imo the Abstract part should focus more on what this proposal provides, instead of the reasoning and context that led to it. Could also merge them into one section if you want.
in bip-xxxx-block-undo.md:15 in 2d75492110
10 | + License: BSD-3-Clause 11 | +``` 12 | + 13 | +# Abstract 14 | + 15 | +Inputs of a Bitcoin block are referenced by the outpoint data structure. This poses a limitation during initial block download (IBD), such that a client must process blocks sequentially to validate the chain history. The SwiftSync protocol allows blocks to be evaluated in arbitrary order, however additional data is required that must be served over the peer-to-peer network. Namely, the creation height, coinbase flag, input script, and amount for each spent coin must be accessible to fully validate a block in a state-less manner. This data cannot be trusted by a peer under usual conditions, however SwiftSync allows a client performing IBD to validate the correctness of this data.
danielabrozzoni commented at 12:56 PM on May 6, 2026:While reading the spec we notice that the bip is about sharing undo data, but that was not clear from the abstract.
I would add a sentence along the lines of "This document describes how to share [this additional data] over the peer to peer network"
jurraca commented at 2:25 PM on May 7, 2026:however additional data is required that must be served over the peer-to-peer network
I would combine this and the next sentence so it's clear what the data is required for at the end of this sentence, e.g. "... in order to validate the blocks, namely the creation height, coinbase flag...".
This data cannot be trusted by a peer under usual conditions
"under usual conditions" doesn't provide much value here, imo it's either trusted or validated, in this case it can't be trusted when served by a peer.
rustaceanrob commented at 8:54 AM on June 26, 2026:Opted to remove "...creation height, coinbase flag." from the abstract as they distracted from the high level. Swapped "under usual conditions" for a more detailed explanation.
in bip-xxxx-block-undo.md:38 in 2d75492110
33 | + 34 | +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. 35 | +## Data structures 36 | +#### Height Code 37 | + 38 | +The height and coinbase flag are encoded as a 32 bit integer. To encode the height and flag, binary left shift the height one bit, treat the boolean as a bit, insert it into the newly opened bit position. To decode the height, binary right shift the code. To decode the coinbase flag, mask the first bit position of the header code and interpret the bit as a boolean.
danielabrozzoni commented at 1:00 PM on May 6, 2026:"To encode the height and flag, binary left shift the height one bit, treat the boolean as a bit, insert it into the newly opened bit position."
I would be slightly more explicit and say "the coinbase flag" instead of "the boolean"
in bip-xxxx-block-undo.md:94 in 2d75492110
89 | +| :---------- | :-------------------------------- | -------------------------------------------------------------- | 90 | +| `blockhash` | 32 byte vector | Block hash these coins are spent from | 91 | +| `len` | `CompactSize(Len(vector<Coins>))` | The length of the coins vector | 92 | +| `coins` | `vector<Coin>` | Coins that were spent, after filtering on the request `cutoff` | 93 | + 94 | +A client supporting the `bspent` MUST include coins created _before_ the `cutoff` field in `getbspent` requests. A client receiving a `bspent` message with un-requested or missing coins MUST disconnect from the serving peer. A client supporting `bspent` MUST adhere to the format of `Coin` specified in the `verion` of the request.
danielabrozzoni commented at 1:16 PM on May 6, 2026:typo: verion -> version
jonatack renamed this:SwiftSync Specification
BIP drafts: SwiftSync Specification
on May 6, 2026jonatack commented at 5:17 PM on May 6, 2026: memberFWIW, I don't mind the unbroken lines and even prefer them. Avoids rejigging line lengths to keep them consistent when updating or having lines with very different lengths.
in bip-xxxx-block-undo.md:30 in 4bb9e9ed4a
25 | +This section defines how to request and serve block spent coins over the peer-to-peer protocol, as well as signaling support of this feature to peers. 26 | +## Definitions 27 | + 28 | +- `[]byte`: arbitrary byte vector 29 | +- `<N bytes>`: size `N` byte vector 30 | +- `vector<Foo>`: arbitrary sized vector of `Foo`
danielabrozzoni commented at 9:12 AM on May 7, 2026:nit: I was a bit confused at first, I would reshape this a little to make it clearer:
[]byte: arbitrary sequence of bytes with no fixed length<N bytes>: byte vector of sizeN, whereNis specified inline (e.g. <32 bytes>)vector<Foo>: vector of arbitrary length of elements of typeFoo
in bip-xxxx-block-undo.md:32 in 4bb9e9ed4a
27 | + 28 | +- `[]byte`: arbitrary byte vector 29 | +- `<N bytes>`: size `N` byte vector 30 | +- `vector<Foo>`: arbitrary sized vector of `Foo` 31 | +- `CompactSize`: encoding of unsigned integers defined in peer-to-peer messages 32 | +- `CompressAmount`: defined in the Function Appendix section
danielabrozzoni commented at 9:15 AM on May 7, 2026:nit: I would be a bit more explicit here:
CompressAmount: compression function for integer amounts, as defined in the Function Appendix section
in bip-xxxx-block-undo.md:56 in 4bb9e9ed4a
51 | +| `0x05` | `P2SH` | `<20 bytes>` | `OP_HASH160 20 <20 bytes> OP_EQUAL` | 52 | +| `0x06` | `P2WSH` | `<32 bytes>` | `OP_0 32 <32 bytes>` | 53 | +| `0x07` | `P2WPKH` | `<20 bytes>` | `OP_0 20 <20 bytes>` | 54 | +| `0x08` | `P2TR` | `<32 byte X-only public key>` | `OP_1 32 <32 bytes>` | 55 | + 56 | +Scripts are serialized in this format by concatenating the `Prefix` and `Format` fields.
danielabrozzoni commented at 9:18 AM on May 7, 2026:I would move this above the table, I kept wondering how to encode until I read this :)
in bip-xxxx-block-undo.md:65 in 4bb9e9ed4a
60 | +#### Coin 61 | + 62 | +| Field | Type | Serialization | Description | 63 | +| :----------------------- | :---------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------- | 64 | +| Input index | 32 bit unsigned integer | Little endian | The index in the block inputs for which this coin corresponds. The coinbase inputs are _excluded_ from this index | 65 | +| Height and coinbase flag | Height code | Little endian | |
danielabrozzoni commented at 9:20 AM on May 7, 2026:I think this should have "Defined above" in "Serialization"
in bip-xxxx-block-undo.md:21 in 4bb9e9ed4a outdated
16 | +# Motivation 17 | + 18 | +A current limitation of IBD is that it must be done sequentially. This is a result of the height, coinbase flag, input script, and amount of the block inputs being omitted from the data committed to by proof of work in the current block, and, thus, this data cannot be trusted if received over the wire naively. Using the SwiftSync protocol, a client is able to verify the correctness of this data, even if served by a potentially untrusted party. This is a property of the SwiftSync hash aggregate, which commits to the height, coinbase flag, script, and amount when creating and deleting coins. 19 | +# Specification 20 | + 21 | +In Bitcoin Core, to roll-back the chain state in the event of a block reorganization, the height, coinbase flag, script and amount metadata for each input of a block are stored in a data structure known colloquially as "undo data". This terminology stems from its use to "undo" the effect of a block by repopulating the UTXO set with the coins that were spent by the reorganized block. To remain general in language, this data will be referred as "spent coins."
danielabrozzoni commented at 2:21 PM on May 7, 2026:nit: it took me a while to figure out that the coinbase flag is needed in order to check that a transaction is not spending an immature coinbase... It would be nice to have this specified somewhere to avoid confusion, but I'm not sure if it really fits here, so, as you wish
rustaceanrob commented at 8:54 AM on June 22, 2026:Added a small note to the height code section.
danielabrozzoni commented at 2:24 PM on May 7, 2026: memberI did an initial pass and left some comments. I read the BIPs in the commit order (block undo -> histfile -> swiftsync) and it was pretty easy to follow.
in bip-xxxx-block-undo.md:23 in 4bb9e9ed4a outdated
18 | +A current limitation of IBD is that it must be done sequentially. This is a result of the height, coinbase flag, input script, and amount of the block inputs being omitted from the data committed to by proof of work in the current block, and, thus, this data cannot be trusted if received over the wire naively. Using the SwiftSync protocol, a client is able to verify the correctness of this data, even if served by a potentially untrusted party. This is a property of the SwiftSync hash aggregate, which commits to the height, coinbase flag, script, and amount when creating and deleting coins. 19 | +# Specification 20 | + 21 | +In Bitcoin Core, to roll-back the chain state in the event of a block reorganization, the height, coinbase flag, script and amount metadata for each input of a block are stored in a data structure known colloquially as "undo data". This terminology stems from its use to "undo" the effect of a block by repopulating the UTXO set with the coins that were spent by the reorganized block. To remain general in language, this data will be referred as "spent coins." 22 | + 23 | +Bitcoin Core full archival nodes store spent coins for all blocks. This is useful in the context of SwiftSync, as no additional index must be created or maintained to serve this data to peers. There are, however, some discrepancies between how this data is serialized on disk in Bitcoin core and how this proposal seeks to serialize this data over the peer-to-peer protocol, which are detailed in the rationale section.
jurraca commented at 12:59 PM on May 8, 2026:Bitcoin core / Core
jurraca commented at 1:00 PM on May 8, 2026: nonesome writing nits but overall the concept is clear enough.
rustaceanrob force-pushed on May 10, 2026rustaceanrob force-pushed on May 10, 2026murchandamus commented at 11:02 PM on May 12, 2026: memberThanks for the review, @danielabrozzoni and @jurraca, as well as the quick turnaround @rustaceanrob. I notice that this pull request is still marked as a Draft PR. Are you still planning significant changes? If your submission is ready for another BIP Editor review, please mark the PR as "ready for review".
rustaceanrob commented at 11:46 AM on May 14, 2026: memberI will keep these as a draft as the hintsfile format is subject to change.
in bip-xxxx-block-undo.md:20 in f4cd99ae05 outdated
15 | + 16 | +Inputs of a Bitcoin block are referenced by the outpoint data structure. This poses a limitation during initial block download (IBD), such that a client must process blocks sequentially to validate the chain history. The SwiftSync protocol allows blocks to be evaluated in arbitrary order, however additional data is required that must be served over the peer-to-peer network. Namely, the creation height, coinbase flag, input script, and amount for each spent coin must be accessible to fully validate a block in a state-less manner. This document describes how to share this additional data over the peer to peer network. 17 | +## Motivation 18 | + 19 | +A current limitation of IBD is that it must be done sequentially. This is a result of the height, coinbase flag, input script, and amount of the block inputs being omitted from the data committed to by proof of work in the current block, and, thus, this data cannot be trusted if received over the wire naively. Using the SwiftSync protocol, a client is able to verify the correctness of this data, even if served by a potentially untrusted party. This allows a significant improvement in IBD performance, as block downloads may be done in parallel. 20 | +## Specification
Roasbeef commented at 2:01 AM on May 23, 2026:Minor formatting thing, but the document as reads today isn't uniform w.r.t when it decides to add a new line before heading vs not.
in bip-xxxx-block-undo.md:32 in f4cd99ae05 outdated
27 | +### Definitions 28 | + 29 | +- `[]byte`: arbitrary sequence of bytes with no fixed length 30 | +- `<N bytes>`: byte vector of size N, where N is specified inline (e.g. <32 bytes>) 31 | +- `vector<Foo>`: vector of arbitrary length of elements of type Foo 32 | +- `CompactSize`: encoding of unsigned integers defined in peer-to-peer messages
Roasbeef commented at 2:05 AM on May 23, 2026:For the sake of having a complete stand alone document, I think
CompactSizeshould be specified briefly here. Otherwise, it assumes that readers are familiar with the naming/semantic conventions of thebitcoindcodebase.
rustaceanrob commented at 8:53 AM on June 22, 2026:Added to the functional appendix
in bip-xxxx-block-undo.md:30 in f4cd99ae05
25 | + 26 | +This section defines how to request and serve block spent coins over the peer-to-peer protocol, as well as signaling support of this feature to peers. 27 | +### Definitions 28 | + 29 | +- `[]byte`: arbitrary sequence of bytes with no fixed length 30 | +- `<N bytes>`: byte vector of size N, where N is specified inline (e.g. <32 bytes>)
Roasbeef commented at 2:06 AM on May 23, 2026:What encoding is used to specify the length of
N?in bip-xxxx-block-undo.md:72 in f4cd99ae05 outdated
67 | +| Height and coinbase flag | Height code | Defined above | | 68 | +| Script | Reconstructable script format | Defined above | | 69 | +| Amount | 64 bit unsigned integer | Defined above | Satoshi denominated value | 70 | +### Messages 71 | + 72 | +#### MSG_GET_SPENT_COINS
Roasbeef commented at 2:08 AM on May 23, 2026:Is the idea that a peer would issue this request for every block in the chain? If we assume mainnet at height, and a 150 ms round trip time, then a peer would spend nearly 80 hours just downloading this undo data.
You may want to consider a batched variant, similar to the way messages like
getheadersworks.
rustaceanrob commented at 9:44 AM on June 22, 2026:We've found that bandwidth throughput is the limiting factor when downloading blocks in parallel. Not all spent coins have to be downloaded if a client keeps a cache, as this document describes. In the batched variant, the cache is not possible and the bandwidth requirement increases significantly.
in bip-xxxx-block-undo.md:104 in f4cd99ae05
99 | + 100 | +Support for serving historical block undo data is advertised by a service bit. 101 | + 102 | +| Field | Value | 103 | +| :----------------- | :---------- | 104 | +| `NODE_BLOCK_UNDO` | `1 << ???` |
Roasbeef commented at 2:10 AM on May 23, 2026:Rationale should be added for the choice of a new node version over the more common place (as of the past few years) exchange of a
sendXmessage during the version handshake.IMO a version makes sense here, as it can be used to filter out peers upfront that support sending this undo data over the network.
rustaceanrob commented at 9:01 AM on June 23, 2026:I opted for a BIP-434 feature message, which has a similar mechanism for the sendX
in bip-xxxx-block-undo.md:86 in f4cd99ae05 outdated
81 | +| `blockhash` | 32 byte vector | Hash of the block for which inputs are requested | 82 | +| `cutoff` | 32 bit unsigned integer | If set greater than zero, only include coins created _before_ this height | 83 | + 84 | +#### MSG_SPENT_COINS 85 | + 86 | +`MSG_SPENT_COINS` defines the data structure for inputs of a block.
Roasbeef commented at 2:11 AM on May 23, 2026:Probably not really y'all's intended use case, but if you optionally make it possible to include merkle proofs for the set of coins, then this message can be used to obtain a proof that an output was spent in a given block.
Roasbeef commented at 2:12 AM on May 23, 2026:It would actually also be useful for BIP 157+158 peers, as the final version that shipped includes the script spent (instead of the outpoint), which means that if you're using the filters to find a block where a given script has been spent, you need to make some assumptions about what the prev script is for a given transaction.
rustaceanrob commented at 12:32 PM on June 23, 2026:The most recent response on this mailing list post mentions commitment to the UTXO set as part of the block header. There are additional ways to do this outside of a soft fork as well, i.e. utreexo proofs. For now I think it best to leave this unspecified in this version of the message while the community shares ideas, but I do think this is interesting.
in bip-xxxx-swiftsync.md:18 in f4cd99ae05
13 | +## Abstract 14 | + 15 | +_SwiftSync_ is a protocol to accelerate initial block download (IBD) using existing cryptographic primitives and minimal state. The protocol is comprised of hash aggregate for a set of elements and a "hintsfile" to indicate the spent-ness of outputs in the chain history. Using these hints, clients may perform IBD in parallel, which maximizes the use of existing system resources and shifts the performance limitations to internet quality. 16 | +## Motivation 17 | + 18 | +Initial block download is the first user experience when using Bitcoin software, and, moreover, is a bootstrapping cost for second layer protocols. Improvements to this process benefit end-users and scaling protocols alike. IBD faces two limitations. First, although the lifetime of coins demonstrates an empirical distribution, cache misses occur for coins that are deleted. This creates unnecessary disk I/O and database compaction. Secondly, given the structure of a block, coins that are spent are indexed by their outpoint. This creates a requirement for clients to maintain a cache to fetch coin metadata associated with an outpoint. _SwiftSync_ alleviates both of these limitations, allowing for IBD in as fast as a client can download blocks and verify signatures.
yancyribbens commented at 2:01 PM on May 31, 2026:I would think there is also efficiency gains in that the blocks need not be downloaded in linear fashion from peers, and also that blocks can be shared with peers before you have downloaded the entire chain state.
rustaceanrob commented at 8:51 AM on June 22, 2026:This is mentioned in the abstract.
rustaceanrob force-pushed on Jun 3, 2026rustaceanrob commented at 5:07 PM on June 3, 2026: memberWrapped text and standardized formatting with
mdformat, will address outstanding feedback soon.murchandamus commented at 8:25 PM on June 3, 2026: memberGreat, thanks! I’ll give it a read when you’re done with that.
melvincarvalho referenced this in commit 36cdede939 on Jun 20, 2026melvincarvalho referenced this in commit 6ec6902e4d on Jun 20, 2026rustaceanrob force-pushed on Jun 22, 2026rustaceanrob renamed this:BIP drafts: SwiftSync Specification
BIPs: SwiftSync Specification
on Jun 22, 2026rustaceanrob marked this as ready for review on Jun 22, 2026rustaceanrob commented at 8:56 AM on June 22, 2026: memberGiven there are a few clients that have started implementations of SwiftSync, and new hintsfile encodings may simply increment the file version, I am moving these out of draft. Some outstanding comments addressed, others require some additional thought.
rustaceanrob force-pushed on Jun 22, 2026rustaceanrob force-pushed on Jun 22, 2026rustaceanrob force-pushed on Jun 22, 2026rustaceanrob force-pushed on Jun 22, 2026rustaceanrob force-pushed on Jun 23, 2026jonatack removed the label PR Author action required on Jun 23, 2026in bip-xxxx-hintsfile.md:153 in ecbda2aafd outdated
148 | + 149 | +An _unspendable output_ is defined as: 150 | + 151 | +- An output with script length over 10,000 OR 152 | +- An output beginning with `OP_RETURN` OR 153 | +- A BIP-30 unspendable coinbase output
edilmedeiros commented at 7:11 PM on June 24, 2026:I think this would be better defined in the swiftsync spec and just add a link to that document here.
in bip-xxxx-hintsfile.md:164 in ecbda2aafd outdated
159 | +1. Set the current index to `0` 160 | +1. While outputs remain: 161 | + 1. If the output is _unspendable_, continue 162 | + 1. Query the UTXO set. If the output is not in the UTXO set, increment the current index. Otherwise, write the 163 | + current index to the vector and go back to step 3. 164 | +1. Write the Elias-Fano encoding of the vector to file.
edilmedeiros commented at 7:15 PM on June 24, 2026:Codec standards should not specify or describe how the encoder should construct the bitstream, only how the decoder will process the received bitstream. It's up to the implementer to figure out a way to create a valid bitstream since there are potentially many ways to do so. Describing only the decoder semantics is sufficient to define what a valid bitstream is.
rustaceanrob commented at 9:57 AM on June 25, 2026:I don't follow this at all. I did not specify how they construct the elias-fano encoding, but any hintsfile of this format must follow the elias-fano serialization above to be deserialized by a decoder.
edilmedeiros commented at 2:53 PM on June 26, 2026:I mean, this snippet is explaining how a theoretical/simplified encoder works, but this is unnecessary (at best) and can be removed to tighten the document.
rustaceanrob commented at 8:34 PM on June 26, 2026:Sure, I can remove these steps given the serialization is defined already
in bip-xxxx-hintsfile.md:183 in ecbda2aafd
178 | +yet the implementation is concise and does not require dependencies on third party libraries. As of block height 179 | +930,000, the UTXO set may be represented in 119mb with this method, which is well within the 450mb `dbcache` requirement 180 | +in Bitcoin Core, and reasonable for most clients to hold directly in memory. This encoding represents elements in $2n + 181 | +n \\lceil \\log_2(m/n) \\rceil$ bits, which is within a reasonable bound of the theoretical optimum. 182 | + 183 | +Partitioning the hints by block is an intuitive choice, and allows for efficient random access of hints. Groupings of
edilmedeiros commented at 7:28 PM on June 24, 2026:Partitioning the hints by block is an intuitive choice, and allows for efficient random access of hints.
I don't see how this can be true: the bistream has a header (
magic,version,height) followed by a sequence ofEliasFanoitems, each of which are composed byN,M(fixed size info),L,H(variable size info).So, imagine I have a hintsfile. To find data for block
k, one do need to (minimally) process data for block 1 to discover the size of the firstEliasFanoitem (because of the variable size parts). Then, block 2 and so forth, until the intended block target. This would be true if theEliasFanoitems were fixed size among all blocks to allow for offset arithmetic, but the amount of padding would be prohibitively high.Thus, the
hintspayload works more like aList<EliasFano>(requires sequential access) than avector<EliasFano>(allows random access). Of course, the decoder could create an index of offsets, but this is not only an implementation detail, but also something that will add to the required resources to process the hintsfile.
rustaceanrob commented at 8:12 AM on June 25, 2026:Good catch, the original version had a header section, but was removed as it could be reconstructed as you described. I will remove that note.
edilmedeiros commented at 2:58 PM on June 26, 2026:I wonder if having more blocks taken together will not improve compression sensibly (I'll experiment with it). We can add a counter in the bitstream to allow the encoder to choose it freely (at the cost of having more bytes in the bitstream) but we potentially gain:
- Less
H, Lpairs in the bitstream. - More data to feed to the Elias-fano process (tends to push it closer to the theoretical entropy).
in bip-xxxx-hintsfile.md:196 in ecbda2aafd outdated
191 | + 192 | +This document describes how to encode a hintsfile without additional dependencies, but developers and users willing to 193 | +use generic compression algorithms like `gzip` or `zstd` may be able to compress the hints representation further. This 194 | +would indicate there are still optimizations to be made with the format of the hints, however the complexity of the 195 | +encoding and decoding may also increase. Developers and users should encode hints in any format that is suitable for 196 | +their dependency, size, and memory requirements.
edilmedeiros commented at 7:33 PM on June 24, 2026:Developers and users should encode hints in any format that is suitable for their dependency, size, and memory requirements.
This sounds like "I did all that thinking to specify a file format, but you can do whatever you want." which is probably not what was intended.
rustaceanrob commented at 10:02 AM on June 25, 2026:All that is required to do SwiftSync is an agreed upon format between client and server on a hintsfile encoding. Take this comment for example which used
gzipand simple varints for unspent indices.I wrote this document in the context of the Rust ecosystem, which is particularly adverse to adding dependencies, but if someone is comfortable using a generic compression algorithm, they may do so. I personally don't think "download this dependency" is a general solution, but it may work for other clients.
edilmedeiros commented at 1:11 PM on June 25, 2026:I get it, but feels inconsistent with the swiftsync protocol description (
bip-xxx-switfsync.md): line 10 points that the file format bip will be required (after bips are assigned numbers?). This also harms interoperability in the ecosystem.
rustaceanrob commented at 2:41 PM on June 25, 2026:Fair enough. I decided to remove this section entirely.
in bip-xxxx-hintsfile.md:203 in ecbda2aafd
198 | +## Distribution 199 | + 200 | +A malicious hintsfile distributor cannot lead a client to accepting an invalid UTXO set state, but they can expend time 201 | +and resources of a client attempting to perform IBD with SwiftSync. Clients SHOULD obtain a hintsfile from a party that 202 | +has a moral, financial, or otherwise incentive-aligned reason to provide truthful data. Examples of such a party include 203 | +local community leaders or meetup organizers that have a direct social incentive to provide a useful hintsfile to users.
edilmedeiros commented at 7:34 PM on June 24, 2026:Examples of such a party include local community leaders or meetup organizers that have a direct social incentive to provide a useful hintsfile to users.
I'm not sure it's wise to give this kind of advice in a specification, just to point to the risks involved.
in bip-xxxx-hintsfile/test_vectors/elias_fano.json:1 in ecbda2aafd outdated
edilmedeiros commented at 7:37 PM on June 24, 2026:What's the rationale for these test vectors? Are they trying to test specific edge-cases or are just arbitrary cases? If the latter, I think it would be better to pick a couple mainnet blocks and use them to build the test vectors, specially blocks that exercise all the unspendable output cases.
rustaceanrob commented at 10:19 AM on June 27, 2026:These test a few scenarios of the different parameters of the elias-fano encoding, however I agree vectors for the edge cases are also required. I added a
READMEthat points to a few expected hintsfiles for signet and mainnet at very low heights, which tests each unspendable edge case.in bip-xxxx-swiftsync.md:46 in ecbda2aafd
41 | +output (UTXO) set indeed corresponds to the chain history downloaded from peers. 42 | + 43 | +A key invariant is that a UTXO set state at height $n$ is equivalent to all of the outputs created in the chain history, 44 | +less all of the inputs: 45 | + 46 | +$Outputs - UTXO\_{n} = Inputs$
edilmedeiros commented at 7:43 PM on June 24, 2026:Outputs,UTXO\_{n}, andInputsare sets (in the mathematical sense). I feel that-is not as prevalent a notation in this case as\setminus.I would have written
$UTXO\_{n} = Outputs \setminus Inputs$because we are effectively constructingUTXO\_{n}, but not the other sets (that are somehow tracked by the aggregators).
rustaceanrob commented at 10:18 AM on June 25, 2026:The left-hand-side is everything added to the output aggregate and the right-hand-side is everything added to the input aggregate. These are exactly the values we need to assert are equal, and we arrive at the UTXO set as a side effect.
As far as set notation, I didn't even know \setminus was a symbol. For programmers I think a simple
-is more common and what I find the most legible.in bip-xxxx-swiftsync.md:63 in ecbda2aafd
58 | +client may compute two aggregates, and compare the values at the end of the protocol. The _aggregate_ is defined over 59 | +the data structure of the elements and a hashing function. It is recommended, but not strictly required, that a client 60 | +uses the typical SHA-256 hash, with an additional randomly generated salt value[^2]. The elements of the set a client 61 | +compares are _coins_, which are defined as the following: 62 | + 63 | +$Coin = Creation Height + Coinbase Flag + Output Script + Amount + Outpoint$
edilmedeiros commented at 7:45 PM on June 24, 2026:We are effectively building bit patterns that will serve as hash preimages, not numbers, so:
$Coin = Creation Height || Coinbase Flag || Output Script || Amount || Outpoint$Also, because of that, serialization of each piece of information should be formally defined, e.g. https://github.com/bitcoin/bips/blob/861e235e93b40e84e86652ef6e80c2f2dbfc1e17/bip-0340.mediawiki?plain=1#L96-L120
in bip-xxxx-swiftsync.md:85 in ecbda2aafd outdated
80 | +1. Using the undo data, validate the block. A non-exhaustive but explicit list of steps include: 81 | + 1. Check the coinbase does not over-claim the block subsidy 82 | + 1. Check the number of signature operations 83 | + 1. Validate all script executions succeed 84 | + 1. Validate non-contextual checks like merkle roots and timestamps 85 | + 1. If the block is invalid, disconnect the peer. If the block is valid, continue
edilmedeiros commented at 7:54 PM on June 24, 2026:1. Using the undo data, validate the block. If the block is invalid, fail.- Since the validation list is not exhaustive and since consensus is not formally defined anyhow, better to leave it out.
If the block is valid continuedoesn't specify what to do in the case the block is invalid, it's implicit we should continue...
in bip-xxxx-swiftsync.md:86 in ecbda2aafd outdated
81 | + 1. Check the coinbase does not over-claim the block subsidy 82 | + 1. Check the number of signature operations 83 | + 1. Validate all script executions succeed 84 | + 1. Validate non-contextual checks like merkle roots and timestamps 85 | + 1. If the block is invalid, disconnect the peer. If the block is valid, continue 86 | +1. For all inputs, except the coinbase, add them to $Agg\_{inputs}$
edilmedeiros commented at 8:04 PM on June 24, 2026:This is not wrong or insufficient, although it was specially challenging to grok since
Coinis defined as:Coin = Creation Height + Coinbase Flag + **Output Script + Amount** + OutpointI.e. which output script and amount should I use when processing an input?
By doing a manual toy example, I figured out one should "dereference" the outpoint and retrieve data from a previous transaction (which might live in a different block, which might force sequential processing). If this understanding is right, we are back at square one. IIUC, this info is in the undo data, but it is not mentioned here.
rustaceanrob commented at 12:14 PM on June 25, 2026:I added "using the spent coin data" to make it clear which output script, amount, etc is used
in bip-xxxx-swiftsync.md:90 in ecbda2aafd outdated
85 | + 1. If the block is invalid, disconnect the peer. If the block is valid, continue 86 | +1. For all inputs, except the coinbase, add them to $Agg\_{inputs}$ 87 | +1. For all outputs: 88 | + 1. If the output is _unspendable_, continue 89 | + 1. Add the output to $UTXO\_{n}$ if the output is in $Hintsfile\_{n}$ and continue 90 | + 1. Otherwise, add the output to $Agg\_{outputs}$
edilmedeiros commented at 8:12 PM on June 24, 2026:1. For each output: 1. If the output is _unspendable_, continue. 1. If the output is marked unspent in $Hintsfile\_{n}$, add it to $UTXO\_{n}$. Else, add the output to $Agg\_{outputs}$.Also, see the other comment about the
unspendabledefinition. I think it should be here, instead.
rustaceanrob commented at 10:14 AM on June 25, 2026:Added to the
Definitionssectionin bip-xxxx-swiftsync.md:94 in ecbda2aafd outdated
89 | + 1. Add the output to $UTXO\_{n}$ if the output is in $Hintsfile\_{n}$ and continue 90 | + 1. Otherwise, add the output to $Agg\_{outputs}$ 91 | + 92 | +Notice here that a client does not have to download blocks in any particular order, and may download blocks from 93 | +multiple peers at a time. A client then verifies $Agg\_{outputs} = Agg\_{inputs}$ once they have arrived at height 94 | +$n$[^1]. If the verification succeeds, the client accepts $UTXO\_{n}$ as valid. In the failure case, the client rejects
edilmedeiros commented at 8:13 PM on June 24, 2026:nit: out of order footnote number.
in bip-xxxx-swiftsync.md:135 in ecbda2aafd
130 | + 131 | +- [`swiftsync`](https://github.com/2140-dev/swiftsync) Rust implementation 132 | + 133 | +## Acknowledgements 134 | + 135 | +Kudos to my colleague Ruben Somsen for creating the protocol described in this specification
edilmedeiros commented at 8:15 PM on June 24, 2026:Since Ruben is a co-author, it's really weird to have this here.
in bip-xxxx-swiftsync.md:75 in ecbda2aafd
70 | + 71 | +### Protocol 72 | + 73 | +Block validation when performing _SwiftSync_ is nearly the same, only with a few additional steps. First, a client 74 | +requires a $Hintsfile\_{n}$ and two aggregates, one for block inputs $Agg\_{inputs}$, one for block outputs 75 | +$Agg\_{outputs}$
edilmedeiros commented at 8:22 PM on June 24, 2026:requires a $Hintsfile\_{n}$ and initializes two aggregates with the same value, one for block inputs $Agg\_{inputs}$, the other for block outputs $Agg\_{outputs}$.- The two aggregators should be initialized with the same value, otherwise validation will fail. Intuitively, they should start as 0, and I feel this should be specified, but I'm not sure if there might be any advantage to use a e.g. random value.
- Using
requiresfor something that comes from the outside world (the hintsfile) and for the aggregators suggest they also come from an external source, but they are managed internally only.
edilmedeiros commented at 8:29 PM on June 24, 2026: noneThanks for documenting the protocol in this draft.
Did a deep dive together with the guys from @vinteumorg and left many comments concerning conceptual aspects of the BIPs. I have many editing suggestions, but left them for a second round after the higher-level aspects are more mature.
in bip-xxxx-block-undo.md:4 in ecbda2aafd outdated
0 | @@ -0,0 +1,269 @@ 1 | +``` 2 | + BIP: ? 3 | + Layer: Peer Services 4 | + Title: Peer sharing of block spent coins
johnnyasantoss commented at 9:08 PM on June 24, 2026:nit: the naming is inconsistent in these files. Some places use the blockundo terminology and some (like featureid blockspent)
rustaceanrob commented at 9:02 AM on June 25, 2026:Grepped and removed all "block undo" omitting the nomenclature explanation
in bip-xxxx-block-undo.md:139 in ecbda2aafd outdated
134 | +Support for serving historical block undo data is advertised by a feature message, introduced by 135 | +[BIP-434](https://github.com/bitcoin/bips/blob/master/bip-0434.md). 136 | + 137 | +| featureid | featuredata | 138 | +| :------------------ | :---------- | 139 | +| `blockspentcoinsv1` | `0x00` |
johnnyasantoss commented at 9:25 PM on June 24, 2026:nit: this version in feature name may confuse readers with encoding version described for
Coin.
rustaceanrob commented at 8:46 AM on June 25, 2026:Not sure I follow. I think
Coinis only described as a serialization format but does not specify a version AFICT
rustaceanrob commented at 11:55 AM on June 25, 2026:Oh got it. The version supported by the server is now implied by
featuredata, so theMSG_GET_SPENT_COINSversion can be omitted entirely.in bip-xxxx-block-undo.md:151 in ecbda2aafd outdated
146 | +The lifetime, or interval between creation and spending height, of the coins on the Bitcoin blockchain demonstrate an 147 | +empirical phenomena that the majority of coins are spent within 100 blocks. In fact, approximately 41 percent of coins 148 | +are spent within 10 blocks at the time of writing[^1]. Clients may leverage this to reduce the bandwidth required to 149 | +fetch undo data by using an in-memory cache. For example, a client may store coins that were created in a 5 block 150 | +window, and request only coins that are older than this height via the `cutoff` filter. This results in a significant 151 | +bandwidth reduction at the cost of a cache that can be set dynamically by the client depending on available memory.
johnnyasantoss commented at 9:42 PM on June 24, 2026:This cutoff cache optimization seems to nudge implementors back to sequentially processing blocks with the added burden of requesting extra data over the wire.
Also with the current messages I still need to get the data for the block (even if there's only one unspent cache miss?), right? If that's true, wouldn't a parameter for inputs of interest (delta encoded index) help here?
At
150ms RTT * 955233blocks that's~39.8 hrsof round-trip latency for uncached requests alone, before counting download time (as Roasbeef noted in an earlier review). It seems to me that the cache mitigates this but at the cost of reintroducing the very sequentiality it aims to eliminate.Is this understanding correct?
RubenSomsen commented at 9:09 AM on June 25, 2026:seems to nudge implementors back to sequentially processing blocks
Caching requires sequential processing, but you can have multiple sequential threads in parallel.
added burden of requesting extra data over the wire
You're going to have to request the undo data regardless for non-assumevalid SwiftSync - it is not related to caching.
I still need to get the data for the block (even if there's only one unspent cache miss?), right?
It seems to me that the cache mitigates [round-trip latency]
Caching does not prevent the need for requesting undo data. You can safely assume pretty much every block has cache misses. No cache missses is equivalent to having the full UTXO set (and impossible with multiple sequential threads), which defeats the point.
round-trip latency for uncached requests
I have no strong opinion on batching, but round-trip latency won't add up sequentially if requests are sent out in parallel.
Concrete example: Let's say you're starting another sequential thread from block height 1001 and you intend to cache the last 5 blocks worth of outputs. For the first block you'd request the full undo data. For block 1002 until 1005 you'd request everything created until block height 1000. From height 1006 onwards your 5-block window starts to shift so you'd request everything created until block height 1001, and so on.
All this data can be requested in parallel. As long as your caching strategy is not based on what you witnessed during the previous block, at no point do you have to wait for one block to finish processing before requesting the data for upcoming blocks.
johnnyasantoss commented at 10:00 PM on June 24, 2026: noneI participated with @edilmedeiros in the review and had a few concept concerns, most linked to the undo data, its tradeoff (the worst case scenario seems to be really bad) and the optional 5-block index.
rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 25, 2026rustaceanrob force-pushed on Jun 26, 2026in bip-xxxx-block-undo.md:6 in 2606bd84a1 outdated
0 | @@ -0,0 +1,267 @@ 1 | +``` 2 | + BIP: ? 3 | + Layer: Peer Services 4 | + Title: Peer sharing of block spent coins 5 | + Authors: Robert Netzke <bips@2140.dev> 6 | + Deputies: Ruben Somsen <bips@2140.dev>
murchandamus commented at 11:20 PM on June 26, 2026:I’m confused by this email address. This should be email addresses of the authors, so that they can be contacted by interested parties.
in bip-xxxx-block-undo.md:23 in 2606bd84a1 outdated
18 | +protocol allows blocks to be evaluated in arbitrary order, however additional data is required that must be served over 19 | +the peer-to-peer network. This document describes how to share this data over the peer to peer network. 20 | + 21 | +## Motivation 22 | + 23 | +A current limitation of IBD is that it must be done sequentially. This is a result of the height, coinbase flag, input
murchandamus commented at 11:39 PM on June 26, 2026:A current limitation of IBD is that it must be done sequentially.
Given the postulation or existence of alternative syncing models, that feels a bit loaded. Maybe mention that this specifically refers to Bitcoin Core or alternatively consider something along the lines of: "The common approach to IBD is to process blocks sequentially as that ensures the existence of TXO details when input validation requires them to be available."
This is a result of the height, coinbase flag, input script, and amount of the block inputs being omitted from the data committed to by proof of work in the current block
This is jumping several steps from the prior statement at once. Maybe you could segue that a bit more, e.g., by mentioning that fields you introduce are TXO details, before going into them being only implicitly or not at all committed to by transaction inputs, before explaining how that makes it impossible to verify what is provided by a peer.
in bip-xxxx-block-undo.md:27 in 2606bd84a1 outdated
22 | + 23 | +A current limitation of IBD is that it must be done sequentially. This is a result of the height, coinbase flag, input 24 | +script, and amount of the block inputs being omitted from the data committed to by proof of work in the current block, 25 | +and, thus, this data cannot be trusted if received over the wire naively. Using the SwiftSync protocol, a client is able 26 | +to verify the correctness of this data, even if served by a potentially untrusted party. This allows a significant 27 | +improvement in IBD performance, as block downloads may be done in parallel.
murchandamus commented at 11:48 PM on June 26, 2026:This is a bit imprecise: block download is always done in parallel, it’s just validation that is sequential. Do you mean that block validation can be parallelized?
in bip-xxxx-block-undo.md:32 in 2606bd84a1 outdated
27 | +improvement in IBD performance, as block downloads may be done in parallel. 28 | + 29 | +## Specification 30 | + 31 | +In Bitcoin Core, to roll-back the chain state in the event of a block reorganization, the height, coinbase flag, script 32 | +and amount metadata for each input of a block are stored in a data structure known colloquially as "undo data". This
murchandamus commented at 11:52 PM on June 26, 2026:Maybe I’m a bit to nitpicky here, but these seem to be properties of the spent TXO, not the input.
Edit: I see that you introduce the term spent coin below, which is also fine, but maybe you want to be more precise either way.
and amount metadata for each spent TXO of a block are stored in a data structure known colloquially as "undo data". This
murchandamus commented at 11:12 PM on June 29, 2026:Since git is inherently meant to compare two documents line by line, please avoid reformatting entire paragraphs between commits. It shifts around all line breaks and makes it more work for reviewers to figure out what changed. Rather, leave linebreaks in the same spots, by letting the edited line be a bit longer or shorter to make it easier on reviewers to follow along what changed between two commits. Since the markdown file is just the "source code" of the rendered document, a few lines being a few characters longer or shorter is not an issue. If a line becomes too long, you can split it into two lines, but still leave the lines below unchanged.
I.e., when you changed this paragraph, the diff was:
-and amount metadata for each input of a block are stored in a data structure known colloquially as "undo data". This -terminology stems from its use to "undo" the effect of a block by repopulating the UTXO set with the coins that were -spent by the reorganized block. To remain general in language, this data will be referred as "spent coins." +and amount metadata for each spend transaction output of a block are stored in a data structure known colloquially as +"undo data". This terminology stems from its use to "undo" the effect of a block by repopulating the UTXO set with the +coins that were spent by the reorganized block. To remain general in language, this data will be referred as "spent +coins."<img width="1318" height="161" alt="image" src="https://github.com/user-attachments/assets/caa3cac8-4fa0-47b0-ac57-e4c9602048e0" />
but it would have been much easier to see what changed if the linebreaks had stayed at the same spots:
-and amount metadata for each input of a block are stored in a data structure known colloquially as "undo data". This +and amount metadata for each spend transaction output of a block are stored in a data structure known colloquially as "undo data". This<img width="1492" height="94" alt="image" src="https://github.com/user-attachments/assets/67cf2eb1-b24a-49f1-927b-5c1e45afb276" />
Especially, on GitHub, this renders without highlights, so it takes much longer to find the differences: <img width="892" height="167" alt="image" src="https://github.com/user-attachments/assets/5faa329a-9fe1-4050-a6e7-e7315989df67" />
in bip-xxxx-block-undo.md:62 in 2606bd84a1 outdated
57 | +### Data structures 58 | + 59 | +#### Height Code 60 | + 61 | +When validating a block, a client must confirm coinbase outputs are mature, which is given by the height of the coin. 62 | +The height and coinbase flag are encoded as a 32 bit integer. To encode the height and flag, binary left shift the
murchandamus commented at 11:55 PM on June 26, 2026:Maybe you could add a footnote why both are stored in one data structure, and/or mention here that even with sacrificing one bit, heights up to 2,147,483,647 can be expressed and 30,000+ years of blocks is plenty planning horizon? :p
in bip-xxxx-block-undo.md:59 in 2606bd84a1 outdated
54 | +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and 55 | +"OPTIONAL" in this document are to be interpreted as described in RFC 2119. 56 | + 57 | +### Data structures 58 | + 59 | +#### Height Code
murchandamus commented at 11:59 PM on June 26, 2026:Why is it called "Height Code" when it encodes both height and coinbase flag?
in bip-xxxx-block-undo.md:67 in 2606bd84a1 outdated
62 | +The height and coinbase flag are encoded as a 32 bit integer. To encode the height and flag, binary left shift the 63 | +height one bit, treat the coinbase flag as a bit, insert it into the newly opened bit position. To decode the height, 64 | +binary right shift the code. To decode the coinbase flag, mask the first bit position of the header code and interpret 65 | +the bit as a boolean. 66 | + 67 | +Take, for example, a height with binary encoding `0010 0111`. To encode a coinbase output at this height, one begins
murchandamus commented at 12:00 AM on June 27, 2026:Nit: that’s not a 32-bit integer. ;)
in bip-xxxx-block-undo.md:72 in 2606bd84a1 outdated
67 | +Take, for example, a height with binary encoding `0010 0111`. To encode a coinbase output at this height, one begins 68 | +with a left shift: `0100 1110`, and places the coinbase flag in the least significant bit: `0100 1111`. 69 | + 70 | +#### Reconstructable Script Format 71 | + 72 | +Scripts are serialized in this format by concatenating the `Prefix` and `Format` fields specified below.
murchandamus commented at 12:09 AM on June 27, 2026:This table could use a bit more context. E.g., you could mention:
- What the columns refer to
- that the table introduces a serialization that allows compressing standard output types with addresses and P2PK
- Bare scripts and future output types are not compressed
in bip-xxxx-block-undo.md:80 in 2606bd84a1 outdated
75 | +| :----- | :------- | :------------------------------------ | :----------------------------------------------------------- | 76 | +| `0x00` | Unknown | `CompactSize(Len([]bytes)) + []bytes` | `[]bytes` | 77 | +| `0x01` | `P2PKH` | `<20 bytes>` | `OP_DUP OP_HASH160 20 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG` | 78 | +| `0x02` | `P2PK` | `<32-byte public key (0x02 parity)>` | `33 0x02 <32 byte public key> OP_CHECKSIG` | 79 | +| `0x03` | `P2PK` | `<32-byte public key (0x03 parity)>` | `33 0x03 <32 byte public key> OP_CHECKSIG` | 80 | +| `0x04` | `P2PK` | `<64 byte public key>` | `65 0x04 <64 byte public key> OP_CHECKSIG` |
murchandamus commented at 12:11 AM on June 27, 2026:Given that they are pretty uncommon these days, and it only saves two bytes, have you considered grouping the P2PK outputs with the other bare scripts and just encoding these per the
0x00prefix?in bip-xxxx-block-undo.md:111 in 2606bd84a1 outdated
106 | +Define `cmdString` as `getbspent`. Define BIP-324 message type as ???. 107 | + 108 | +| Field | Type | Description | 109 | +| :---------- | :---------------------- | :------------------------------------------------------------------- | 110 | +| `blockhash` | `<32 bytes>` | Hash of the block for which inputs are requested. | 111 | +| `cutoff` | 32-bit unsigned integer | If greater than zero, include only coins created before this height. |
murchandamus commented at 12:17 AM on June 27, 2026:I could see coins created after a specific height (due to having already processed all blocks up to that height), but why only coins created before a height? Perhaps add an explanation what the
cutoffis useful for?
rustaceanrob commented at 12:44 PM on June 27, 2026:in bip-xxxx-block-undo.md:126 in 2606bd84a1 outdated
121 | +| `blockhash` | `<32 bytes>` | Block hash these coins are spent from. | 122 | +| `len` | `CompactSize(Len(vector<Coin>))` | Length of the coins vector. | 123 | +| `coins` | `vector<Coin>` | Coins spent, after filtering on request `cutoff`. | 124 | + 125 | +A client supporting the `bspent` MUST include coins created _before_ the `cutoff` field in `getbspent` requests. A 126 | +client receiving a `bspent` message with un-requested or missing coins MUST disconnect from the serving peer. A client
murchandamus commented at 12:19 AM on June 27, 2026:Presumably after discarding such a message?
in bip-xxxx-block-undo.md:139 in 2606bd84a1 outdated
134 | +| featureid | featuredata | 135 | +| :------------------ | :---------- | 136 | +| `blockspentcoinsv1` | `0x00` | 137 | + 138 | +A client advertising this service bit SHOULD respond to `getbspent` messages, subject to rate-limiting and bandwidth 139 | +limiting.
murchandamus commented at 12:21 AM on June 27, 2026:Service bits are different from features advertised via BIP434. Was this an incomplete update?
rustaceanrob commented at 12:15 PM on June 27, 2026:Yes, updated
in bip-xxxx-block-undo.md:148 in 2606bd84a1 outdated
143 | +The lifetime, or interval between creation and spending height, of the coins on the Bitcoin blockchain demonstrate an 144 | +empirical phenomena that the majority of coins are spent within 100 blocks. In fact, approximately 41 percent of coins 145 | +are spent within 10 blocks at the time of writing[^1]. Clients may leverage this to reduce the bandwidth required to 146 | +fetch spent coins by using an in-memory cache. For example, a client may store coins that were created in a 5 block 147 | +window, and request only coins that are older than this height via the `cutoff` filter. This results in a significant 148 | +bandwidth reduction at the cost of a cache that can be set dynamically by the client depending on available memory.
murchandamus commented at 12:22 AM on June 27, 2026:Ah cool. I was missing this context above when
cutoffwas introduced.
rustaceanrob commented at 12:41 PM on June 27, 2026:I added a short note when introducing the request message that the
cutofffield is motivated in the rationale section.in bip-xxxx-block-undo.md:154 in 2606bd84a1 outdated
149 | + 150 | +Beyond the use of a dynamic coin height filter, there are additional reasons to not simply read the spent coins from 151 | +disk and send it over the wire. Legacy fields (`nVersion`) are set to `0x00` when writing and reading this data to 152 | +maintain compatibility of disk format with old clients. Furthermore, using the amount compression specified above, an 153 | +11gb reduction in bandwidth is achieved. The application of `VARINT` as opposed to `CompactSize` offers a further 154 | +reduction of 4gb, however the `VARINT` primitive is currently a Bitcoin Core implementation detail. Reusing existing
murchandamus commented at 12:25 AM on June 27, 2026:Given the confusing terminology in regard to
CompactSizeandVARINTand Bitcoin Core, you probably want to define these terms more concretely.in bip-xxxx-block-undo.md:241 in 2606bd84a1 outdated
236 | +``` 237 | + 238 | +## Compatibility 239 | + 240 | +Clients seeking to perform fully-validating SwiftSync require peers that serve undo data. Serving data requires no 241 | +additional index and may be enabled via the service bit.
murchandamus commented at 12:27 AM on June 27, 2026:Re "service bit", please double-check whether you mean to introduce a service bit or a feature.
in bip-xxxx-block-undo.md:10 in 2606bd84a1 outdated
5 | + Authors: Robert Netzke <bips@2140.dev> 6 | + Deputies: Ruben Somsen <bips@2140.dev> 7 | + Status: Draft 8 | + Type: Specification 9 | + Assigned: ? 10 | + License: BSD-3-Clause
murchandamus commented at 12:29 AM on June 27, 2026:Please add the missing Copyright section.
murchandamus commented at 12:37 AM on June 27, 2026: memberI read the first document "Peer sharing of block spent coins". Given my prior knowledge it’s pretty clear what’s going on, but I think people reading about the topic for the first time could use more context in some passages. I noticed a couple sections with potential for improvement.
- The Abstract and first sentences of the Motivation are a bit repetitive.
- For the Definitions and Data Structures sections, I could have used a little more context. What will I be shown? Why? How is the table to be read? What do the columns mean?
rustaceanrob force-pushed on Jun 27, 2026rustaceanrob force-pushed on Jun 27, 2026rustaceanrob force-pushed on Jun 27, 2026rustaceanrob force-pushed on Jun 29, 2026BIP ???: Block spent coins over P2P 92a193e15brustaceanrob force-pushed on Jun 29, 2026rustaceanrob force-pushed on Jun 29, 2026rustaceanrob commented at 8:03 AM on June 29, 2026: memberThank you @murchandamus @Roasbeef @danielabrozzoni @jurraca @johnnyasantoss @yancyribbens @edilmedeiros for the review! The drafts should now be up to date
rustaceanrob commented at 8:05 AM on June 29, 2026: memberI discussed with Ruben on attribution and we decided it makes sense for him to be author on each BIP. @edilmedeiros has agreed to take on deputy as well
in bip-xxxx-hintsfile.md:26 in 1d9f873f79 outdated
21 | +## Motivation 22 | + 23 | +SwiftSync can improve the user experience by accelerating IBD, however the protocol requires the client verify a UTXO 24 | +set corresponds to the blockchain history they received. Rather than simply encoding and distributing the UTXO set, a 25 | +far smaller representation may be computed and shared. Intuitively, just as how it is cheap for programs to share 26 | +pointers to objects in memory, we define a "hintsfile" that encodes pointers to unspent outputs.
murchandamus commented at 5:47 PM on June 29, 2026:The Abstract and Motivation feel a bit mixed up here. Since you’ll have to fill out three Abstracts and three motivations, it might be the easiest to decide which BIP is the first one to be read, and put the motivation of the overarching proposal there.
Then this one could, e.g., simply read: "This document specifies the hintsfile for Swiftsync. The hintsfile stores a compact representation of the UTXO set at a particular height by encoding which TXOs from each block remain unspent."
On the other hand, the motivation should be more focused on what problem this proposal addresses and why this should be adopted, i.e., that the hints file enables skipping all intermediate UTXO set states per foreseeing whether a UTXO is to be retained, that this speeds up IBD, etc. should be in the motivation.
in bip-xxxx-hintsfile.md:61 in 1d9f873f79 outdated
56 | +We define the following: 57 | + 58 | +- Let ${ i\_{0}, ..., i\_{n-1} }$ be a list of $n$ elements where $i\_{n-1} = m$ 59 | +- Let $\\ell(m, n)$ be the function that determines the number of low bits to use: $\\ell(m, n) = \\left\\lfloor \\log_2 60 | + \\ \\left(\\frac{m+1}{n}\\right) \\right\\rfloor$ 61 | +- Let $\\text{unary}(q)$ be the following function: $\\text{unary}(q) = \\underbrace{0\\cdots0}\_{q}1$
murchandamus commented at 5:52 PM on June 29, 2026:This renders oddly:
<img width="825" height="136" alt="Image" src="https://github.com/user-attachments/assets/8081bcef-1a01-4586-8229-69f0f354522b" />
It looks like the 1 and q are not related at all.
murchandamus commented at 10:50 PM on July 1, 2026:This section seems to have more than the necessary escaping. I think this should work fine:
- Let ${ i_{0}, ..., i_{n-1} }$ be a list of $n$ elements where $i_{n-1} = m$ - Let $\ell(m, n)$ be the function that determines the number of low bits to use: $\ell(m, n) = \left\lfloor \log_2 \left(\frac{m+1}{n}\right) \right\rfloor$ - Let $\text{unary}(q)$ be the following function: $\text{unary}(q) = \underbrace{0\cdots0}_{q}1$in bip-xxxx-hintsfile.md:198 in 1d9f873f79 outdated
193 | +## References 194 | + 195 | +- [Research repository](https://github.com/rustaceanrob/swiftsync-research) 196 | +- [Explanatory article](https://t.holmium.no/dia/elias-fano/#_representation_1_fixed_size_compact_encoding) 197 | +- [Paper](https://drops.dagstuhl.de/storage/00lipics/lipics-vol078-cpm2017/LIPIcs.CPM.2017.30/LIPIcs.CPM.2017.30.pdf) 198 | +
murchandamus commented at 6:22 PM on June 29, 2026:Please include a Compatibility Section, even if just to say that there are no compatibility issues.
in bip-xxxx-hintsfile.md:48 in 1d9f873f79 outdated
43 | +to size $m$? In other words, for a block with $n$ unspent outputs, what is an efficient representation? 44 | + 45 | +This formulation has a known theoretical optimum of $\\log_2 \\binom{m}{n}$ bits. _Elias-Fano_ developed a 46 | +representation that is reasonably close to this optimum in a concise and maintainable format. 47 | + 48 | +### Elias-Fano Encoding
murchandamus commented at 6:40 PM on June 29, 2026:I found this description of the encoding too dense to follow. I had to work the example by hand to understand the instructions. Also, some of the instructions are missing and are only mentioned in the example. More detailed suggestions inline.
in bip-xxxx-hintsfile.md:37 in a5579f33e6 outdated
32 | + 33 | +Our goal is to indicate which outputs in a block, or set of blocks, will remain unspent at a particular chain height. 34 | +There are many ways to do so, however an intuitive representation is a 35 | +[bitset](https://en.cppreference.com/w/cpp/utility/bitset.html). Each output in a block is assigned a bit, with a `0` 36 | +bit denoting the output will be spent, and a `1` to denote the output is unspent. For a block of 8 outputs, we may 37 | +arrive at a bitset of `1000 0010`, which conveys the 0th and 6th index are UTXOs.
murchandamus commented at 7:01 PM on June 29, 2026:I looked up the outputs per day for the last ~1000 days from mainnet.observer and divided them by 144 for an educated guess. Some of those days might have more or fewer blocks, so this is probably fairly inaccurate, but by that method I found a minimum of 7200 and a maximum of 10,700 TXOs created per block. I think giving this number would help readers’ intuition why encoding it this way would be very inefficient. I calculated that we could create slightly over 32,000 TXOs in a single block in the past. Maybe consider adding more context along the lines of:
arrive at a bitset of `1000 0010`, which conveys the 0th and 6th index are UTXOs. Actual blocks recently have about 8000–10,000 outputs, but the theoretical maximum is over 32k. Especially for older blocks, very few of these TXOs would remain unspent, so a bitset encoding would take several kilobits of mostly 0s.You could also explain this alternative approach in the Rationale, or take it to the Motivation to explain why Elias-Fano was used. In the specification, it seems a bit out of place.
in bip-xxxx-hintsfile.md:43 in a5579f33e6
38 | + 39 | +Empirically, this representation does poorly, as the vast majority of outputs are spent. In fact, simply recording the 40 | +indices within the block that will be unspent is a more optimal approach than the bitset. For our example above, that 41 | +would be recording the numbers `0, 6`. To efficiently represent this data, we may formulate the problem as the 42 | +following: what is the most efficient way to represent $n$ random, monotonically increasing indices less than or equal 43 | +to size $m$? In other words, for a block with $n$ unspent outputs, what is an efficient representation?
murchandamus commented at 7:04 PM on June 29, 2026:Maybe:
following: what is the most efficient way to represent a small count $n$ random, monotonically increasing indices in the range $0$ to $m$? In other words, for a block with $n$ unspent outputs, what is an efficient representation?in bip-xxxx-hintsfile.md:51 in a5579f33e6 outdated
46 | +representation that is reasonably close to this optimum in a concise and maintainable format. 47 | + 48 | +### Elias-Fano Encoding 49 | + 50 | +Suppose we would like to encode $n$ monotonically increasing elements ${ i\_{0}, ..., i\_{n - 1} }$ where $i\_{n - 1} = 51 | +m$. _Elias-Fano_ builds on the intuition that numbers may share bits in their binary representation. Consider the
murchandamus commented at 7:07 PM on June 29, 2026:m$. _Elias-Fano_ builds on the intuition that in a sequence of monotonically increasing numbers the least significant bits differ while the most significant bits of numbers increase only gradually. Consider thein bip-xxxx-hintsfile.md:53 in a5579f33e6 outdated
48 | +### Elias-Fano Encoding 49 | + 50 | +Suppose we would like to encode $n$ monotonically increasing elements ${ i\_{0}, ..., i\_{n - 1} }$ where $i\_{n - 1} = 51 | +m$. _Elias-Fano_ builds on the intuition that numbers may share bits in their binary representation. Consider the 52 | +integers 6 and 7. The binary representation of 6 is `0110` while the binary representation of 7 is `0111`, differing by 53 | +only one bit. This observation may be used to efficiently store elements. For the lowest bits of the elements, we will
murchandamus commented at 7:16 PM on June 29, 2026:This example didn’t help me. I would suggest either dropping it or elaborating to explain the distinction between the most significant bits and less significant bits.
m$. _Elias-Fano_ builds on the intuition that numbers may share bits in their binary representation. This observation may be used to efficiently store elements. For the lowest bits of the elements, we willm$. _Elias-Fano_ builds on the intuition that numbers may share bits in their binary representation. Consider for example the three random integers 2 , 5, and 7. In binary of 2 is `0010`, 5 is `0101`, and 7 is `0111`. Splitting them into the two most significant bits and two least significant bits, the most significant two bits are slowly counting up `00`, `01`, and `01`, while the least significant two bits don’t follow a pattern, `10`, `01`, and `11`. This observation may be used to efficiently store elements. For the lowest bits of the elements, we willin bip-xxxx-hintsfile.md:54 in a5579f33e6 outdated
49 | + 50 | +Suppose we would like to encode $n$ monotonically increasing elements ${ i\_{0}, ..., i\_{n - 1} }$ where $i\_{n - 1} = 51 | +m$. _Elias-Fano_ builds on the intuition that numbers may share bits in their binary representation. Consider the 52 | +integers 6 and 7. The binary representation of 6 is `0110` while the binary representation of 7 is `0111`, differing by 53 | +only one bit. This observation may be used to efficiently store elements. For the lowest bits of the elements, we will 54 | +represent them in a bitset, and for the highest bits, we will represent the difference in bits as unary.
murchandamus commented at 7:17 PM on June 29, 2026:Just their difference?
represent them in a bitset, and for the highest bits, we will represent their difference as unary.in bip-xxxx-hintsfile.md:63 in a5579f33e6 outdated
58 | +- Let ${ i\_{0}, ..., i\_{n-1} }$ be a list of $n$ elements where $i\_{n-1} = m$ 59 | +- Let $\\ell(m, n)$ be the function that determines the number of low bits to use: $\\ell(m, n) = \\left\\lfloor \\log_2 60 | + \\ \\left(\\frac{m+1}{n}\\right) \\right\\rfloor$ 61 | +- Let $\\text{unary}(q)$ be the following function: $\\text{unary}(q) = \\underbrace{0\\cdots0}\_{q}1$ 62 | + 63 | +We start by determining $\\ell$ for a given $n$ and $m$. For each $i$, take the $\\ell$ least significant bits and
murchandamus commented at 7:34 PM on June 29, 2026:Maybe this is obvious to smarter people, but it might be helpful to keep the reader abreast of how many bits are being encoded. ;)
Numbers up to $m$ are represented with up to $\\lceil log_2(m+1)\\rceil$ bits in binary. We start by determining how the bits are split by calculating $\\ell$ for a given $n$ and $m$. For each $i$ in ascending order, take the $\\ell$ least significant bits andin bip-xxxx-hintsfile.md:65 in a5579f33e6 outdated
60 | + \\ \\left(\\frac{m+1}{n}\\right) \\right\\rfloor$ 61 | +- Let $\\text{unary}(q)$ be the following function: $\\text{unary}(q) = \\underbrace{0\\cdots0}\_{q}1$ 62 | + 63 | +We start by determining $\\ell$ for a given $n$ and $m$. For each $i$, take the $\\ell$ least significant bits and 64 | +append them, most significant bit ordering, to a bitset $L$. Next, iterate over each element and take the remaining most 65 | +significant bits, then record the difference between the last element's high bits and the current element's high bits.
murchandamus commented at 7:35 PM on June 29, 2026:append them, most significant bit ordering, to a bitset $L$. Next, iterate over each element and interpret the remaining most significant bits as a number, then record the difference between the last element's high bits and the current element's high bits. The first element records the difference to 0 as there is no preceding element.in bip-xxxx-hintsfile.md:71 in a5579f33e6
66 | +Record that number using the $\\text unary$ function, and append the unary to a vector $H$. The final representation is 67 | +$m$, $n$, $L$, $H$. 68 | + 69 | +### Worked Example 70 | + 71 | +Suppose $S = [3, 7, 12]$. Then $n=3$ and $m=12$.
murchandamus commented at 7:36 PM on June 29, 2026:Suppose we want to encode a sequence of numbers $S = [3, 7, 12]$. Then $n=3$ and $m=12$. Numbers up to 15 are encoded in four bits in binary.in bip-xxxx-hintsfile.md:84 in a5579f33e6
79 | + 80 | +| Element | Binary | Upper (`value >> 2`) | Lower (`value & 0b11`) | 81 | +| :------ | :----- | :------------------- | :--------------------- | 82 | +| 3 | `0011` | `00` → 0 | `11` → 3 | 83 | +| 7 | `0111` | `01` → 1 | `11` → 3 | 84 | +| 12 | `1100` | `11` → 3 | `00` → 0 |
murchandamus commented at 7:38 PM on June 29, 2026:The conversion to decimal makes sense for the upper, but it feels odd for the lower bits, since they are used as bits.
| Element | Binary | Upper (`value >> 2`) | Lower (`value & 0b11`) | | :------ | :----- | :------------------- | :--------------------- | | 3 | `0011` | `00` → 0 | `11` | | 7 | `0111` | `01` → 1 | `11` | | 12 | `1100` | `11` → 3 | `00` |in bip-xxxx-hintsfile.md:79 in a5579f33e6 outdated
74 | + 75 | +We start by computing $\\ell$: 76 | + 77 | +$\\ell = \\left\\lfloor \\log_2\\left(\\frac{m+1}{n}\\right) \\right\\rfloor = \\left\\lfloor 78 | +\\log_2\\left(\\frac{13}{3}\\right) \\right\\rfloor = \\lfloor \\log_2(4.33) \\rfloor = \\lfloor 2.11 \\rfloor = 2$ 79 | +
murchandamus commented at 7:39 PM on June 29, 2026:We write out the binary representation for all elements in the sequence $S$ and split them into upper and lower bits:in bip-xxxx-hintsfile.md:94 in a5579f33e6
89 | +111100$. 90 | + 91 | +#### 3. Encode the high bits 92 | + 93 | +The upper values are $0, 1, 3$. We encode the gaps between consecutive upper values in unary. Note that the first 94 | +element does not have a previous upper value to compare to, so $0$ is used.
murchandamus commented at 7:42 PM on June 29, 2026:Also mentioned above, but the instructions for the first element should also be in the specification rather just in the example.
The upper values are $0, 1, 3$. We encode the gaps between consecutive upper values in unary. Since the first element does not have a previous upper value, it is encoded as the difference to $0$.murchandamus commented at 7:49 PM on June 29, 2026: memberDid a first read of "Hints for unspent coins"
murchandamus commented at 11:23 PM on June 29, 2026: memberWill read the third document some time in the next few days and then circle back.
rustaceanrob force-pushed on Jun 30, 2026BIP ???: Unspent outputs hintsfile c4415383ccBIP ???: SwiftSync specification 2abf06aa05rustaceanrob force-pushed on Jun 30, 2026in bip-xxxx-swiftsync.md:18 in 2abf06aa05
13 | +``` 14 | + 15 | +## Abstract 16 | + 17 | +_SwiftSync_ is a protocol to accelerate initial block download (IBD) using existing cryptographic primitives and minimal 18 | +state. The protocol is comprised of hash aggregate for a set of elements and a "hintsfile" to indicate the spent-ness of
murchandamus commented at 9:57 PM on July 1, 2026:Missing article?
state. The protocol is comprised of a hash aggregate for a set of elements and a "hintsfile" to indicate the spent-ness ofin bip-xxxx-swiftsync.md:30 in 2abf06aa05
25 | +for second layer protocols. Improvements to this process benefit end-users and scaling protocols alike. IBD faces two 26 | +limitations. First, although the lifetime of coins demonstrates an empirical distribution, cache misses occur for coins 27 | +that are deleted. This creates unnecessary disk I/O and database compaction. Secondly, given the structure of a block, 28 | +coins that are spent are indexed by their outpoint. This creates a requirement for clients to maintain a cache to fetch 29 | +coin metadata associated with an outpoint. _SwiftSync_ alleviates both of these limitations, allowing for IBD in as fast 30 | +as a client can download blocks and verify signatures.
murchandamus commented at 10:01 PM on July 1, 2026:Some of these might be implementation specific, and that should perhaps be noted in those cases. ;)
in bip-xxxx-swiftsync.md:38 in 2abf06aa05
33 | + 34 | +### Definitions 35 | + 36 | +- $H$: A hashing function 37 | +- $Hintsfile\_{n}$: Defined in BIP ??? 38 | +- $UTXO\_{n}$: Unspent outputs at block height $n$
murchandamus commented at 10:04 PM on July 1, 2026:Here and in several instances below, the rendered "UTXO" has weird spacing. I didn’t test, but would the following maybe work?
<img width="688" height="214" alt="Image" src="https://github.com/user-attachments/assets/cb3424cb-54b0-46bc-ae76-663a0372e26c" />
- $\text{UTXO}_{n}$: Unspent outputs at block height $n$Also note, that the underscore doesn’t need to be escaped as far as I’m aware, and that seems to cause oddities in some Mathjax interpreters.
in bip-xxxx-swiftsync.md:41 in 2abf06aa05
36 | +- $H$: A hashing function 37 | +- $Hintsfile\_{n}$: Defined in BIP ??? 38 | +- $UTXO\_{n}$: Unspent outputs at block height $n$ 39 | + 40 | +_SwiftSync_ builds on a common observation in cryptography, that _verification_ is often orders of magnitude more 41 | +performant than _computation_. What a client seeks to verify when performing _SwiftSync_ is that a unspent transaction
murchandamus commented at 10:06 PM on July 1, 2026:This observation is broader than cryptography, it applies to computing in general, but also to math (e.g., it is much easier to verify the square root of a number than to calculate it).
murchandamus commented at 10:09 PM on July 1, 2026:While the verification vs computation thing is true, I would describe SwiftSync’s speedup as being achieved by foregoing manifestation of all the intermediate UTXO sets and skipping directly to the UTXO set at the target height.
in bip-xxxx-swiftsync.md:57 in 2abf06aa05
52 | + 53 | +As a final note, some coins are guaranteed to be impossible to spend. We define an _unspendable output_ is defined as: 54 | + 55 | +- An output with script length over 10,000 OR 56 | +- An output beginning with `OP_RETURN` OR 57 | +- A [BIP-30](https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki) unspendable coinbase output
murchandamus commented at 10:14 PM on July 1, 2026:The capitalized "OR" threw me off for a moment, maybe:
Some coins are impossible to spend. We define any of the following as _unspendable outputs_: - An output with script length over 10,000 - An output beginning with `OP_RETURN` - A [BIP-30](https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki) unspendable coinbase outputin bip-xxxx-swiftsync.md:64 in 2abf06aa05
59 | +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and 60 | +"OPTIONAL" in this document are to be interpreted as described in RFC 2119. 61 | + 62 | +### Aggregation 63 | + 64 | +A client must compare $Outputs - UTXO\_{n}$ with $Inputs$ in a succinct way. Rather than say, comparing the lists, a
murchandamus commented at 10:27 PM on July 1, 2026:Maybe:
A client must compare $\text{Outputs} - \text{UTXO}_{n}$ with $\text{Inputs}$ in a succinct way. Rather than say, comparing the lists, ain bip-xxxx-swiftsync.md:99 in 2abf06aa05
94 | + 95 | +When downloading blocks, _SwiftSync_ clients will do the following: 96 | + 97 | +1. Download the required spent coins data defined in BIP ???. 98 | +1. Using the undo data, validate the block. If the block is invalid, fail. 99 | +1. For all inputs, except the coinbase, add the hashes to $Agg\_{inputs}$ using the spent coin data.
murchandamus commented at 10:31 PM on July 1, 2026:The "coinbase" is the transaction field that replaces the input script in a coinbase transaction input. I think you mean "For all inputs, excluding coinbase inputs,…"?
in bip-xxxx-swiftsync.md:106 in 2abf06aa05
101 | + 1. If the output is _unspendable_, continue 102 | + 1. If the output is in $Hintsfile\_{n}$, add the output to $UTXO\_{n}$. Else, add the hash of the output coin to 103 | + $Agg\_{outputs}$. 104 | + 105 | +Notice here that a client does not have to download blocks in any particular order, and may download blocks from 106 | +multiple peers at a time. A client then verifies $Agg\_{outputs} = Agg\_{inputs}$ once they have arrived at height
murchandamus commented at 10:34 PM on July 1, 2026:In a previous description of SwiftSync, my understanding was that there was only one aggregate, and outputs were added, inputs were deducted. A valid hintsfile would thereby cause the aggregate to result in 0. While this clearly is functionally equivalent, I was curious what the motivation was to split them into two aggregates.
in bip-xxxx-swiftsync.md:125 in 2abf06aa05
120 | +## Note on BIP-30 and BIP-34 121 | + 122 | +During the period between the genesis block and BIP-34 activation, a _SwiftSync_ client must check for duplicate 123 | +coinbase outputs. A cache of these outputs is modest in memory footprint, and may be easily added and queried for the 124 | +fixed block range. More information on this caveat is detailed in 125 | +[this article](https://gist.github.com/RubenSomsen/a02b9071bf81b922dcc9edea7d810b7c).
murchandamus commented at 10:37 PM on July 1, 2026:Given that we can confidently rule out a reorg of more than a decade, wouldn’t it be more practical to hardcode the two exceptions?
in bip-xxxx-swiftsync.md:149 in 2abf06aa05
144 | +- [`swiftsync`](https://github.com/2140-dev/swiftsync) Rust implementation 145 | + 146 | +## References 147 | + 148 | +- [Original proposal](https://gist.github.com/RubenSomsen/a61a37d14182ccd78760e477c78133cd) 149 | +
murchandamus commented at 10:42 PM on July 1, 2026:Please add the required Backwards Compatibility section.
murchandamus commented at 10:42 PM on July 1, 2026: memberThis is my first review of the SwiftSync Initial Block Download document.
murchandamus added the label Needs number assignment on Jul 1, 2026murchandamus commented at 11:07 PM on July 1, 2026: memberLet’s refer to the SwiftSync BIPs as 455, 456, and 457. Please feel free to pick which number should go on each of the three documents.
Please update the file names of the documents and auxiliary files, update the BIP and Assigned headers in the preambles, and add entries in the README.mediawiki table.
murchandamus removed the label Needs number assignment on Jul 1, 2026murchandamus renamed this:BIPs: SwiftSync Specification
BIPs 455–457: SwiftSync Specification
on Jul 1, 2026
github-metadata-mirror
This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-07-09 06:49 UTC