Skip to content

Support Bitcoin Knots BLAKE2b header v2 blocks - #1333

Closed
jasonsopko wants to merge 1 commit into
romanz:masterfrom
jasonsopko:blake2b
Closed

Support Bitcoin Knots BLAKE2b header v2 blocks#1333
jasonsopko wants to merge 1 commit into
romanz:masterfrom
jasonsopko:blake2b

Conversation

@jasonsopko

Copy link
Copy Markdown

What

Support for Bitcoin Knots' BLAKE2b hardfork blocks: a header type that decodes both the legacy 80-byte header and the 164-byte header-v2 form (version bit 31), hashes each the way CBlockHeader::GetHash() does, and the small changes around it so P2P sync, the header chain, the database rows, block indexing and the Electrum calls all accept either form.

Why

Bitcoin Knots v29.4.1 forked mainnet at height 961640 to BLAKE2b proof of work with a longer header. rust-bitcoin's Header is fixed at 80 bytes, so an electrs following a Knots node dies on the first headers message past the fork ("failed to parse unsupported segwit version: 99") and restarts in a loop. Nothing changes for a node on the SHA256d chain: a legacy header decodes, encodes and hashes exactly as before, on-disk rows stay 80 bytes, and a set bit 31 cannot occur there because Core rejects those blocks as bad-version.

The header type and its hash are adapted from Retropex's electrs fork (mempool/electrs lineage, MIT), credited in the module.

How I tested

  • cargo test: the existing suite passes unchanged, plus the five header-v2 vectors from Knots' src/test/data/block_header_v2.json (round trip and block hash), 2000 random v2 headers hashed by an independent Python implementation (set KNOTS_RANDOM_VECTORS), and a check that a legacy header still serializes and hashes byte for byte as bitcoin::block::Header.
  • On a mainnet Knots node past the fork, first against a copy of an existing 59 GB index and then in production: the 961,639 legacy rows loaded as before, the new blocks indexed, blockchain.headers.subscribe returns a 164-byte tip, blockchain.block.header returns 80 bytes for 961639 and 164 for 961640, a block.headers range spanning the fork concatenates correctly, and scripthash.get_history for a coinbase output mined at 961672 returns it with the right balance.

Risk and rollback

No behavior change on a SHA256d chain; the v2 branch is unreachable there. Databases written by this version are readable by the previous one as long as no v2 block has been indexed. Revert the commit.

Still unsure about

Whether you want this behind a Cargo feature (knots-blake2b, default off) to keep the blake2 dependency out of the default build. The code splits cleanly that way; I left it unconditional because the legacy path is identical either way, but I will gate it if you prefer.

Bitcoin Knots v29.4.1 forks mainnet at height 961640 to a BLAKE2b
proof of work with a 164-byte header (version bit 31 set) and a new
block hash rule. rust-bitcoin's Header is fixed at 80 bytes, so
electrs died on the first headers message past the fork ("failed to
parse unsupported segwit version: 99") and restarted in a loop.

Replace bitcoin::block::Header with a knots::BlockHeader that decodes
and encodes both forms and hashes each the way CBlockHeader::GetHash()
does; the type and hash are adapted from Retropex's electrs fork (MIT).
Around it:

- p2p: parse "headers" entries as header + tx count instead of as an
  empty Block, and check a received block's hash with the new type.
- chain: build on knots::BlockHeader; the genesis header converts.
- types/db: header rows are now 80 or 164 bytes. Existing databases
  keep working: legacy rows decode as before and new rows append.
- index: walk a block by hand (header, count, transactions through the
  bitcoin_slices visitor) since bsl::Block assumes an 80-byte header.
- electrum: unchanged code; block headers are served at their real
  length, so blockchain.block.header returns 328 hex characters for a
  BLAKE2b block.

Tests: the five header vectors from Knots' src/test/data/block_header_v2.json
(round trip and block hash), 2000 random v2 headers hashed by an
independent Python implementation (set KNOTS_RANDOM_VECTORS), and a
check that a legacy header still serializes and hashes exactly as
bitcoin::block::Header does. The existing suite passes unchanged.
@romanz

romanz commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Closing due to https://github.com/rust-bitcoin/rust-bitcoin#policy-on-altcoinsaltchains:

Since the altcoin landscape includes projects which frequently appear and disappear, and are poorly designed anyway we do not support any altcoins. Supporting Bitcoin properly is already difficult enough, and we do not want to increase the maintenance burden and decrease API stability by adding support for other coins.

Our code is public domain so by all means fork it and go wild :)

@romanz romanz closed this Aug 30, 2026
@luke-jr

luke-jr commented Aug 30, 2026

Copy link
Copy Markdown

Not applicable, since this is for Bitcoin itself

@jasonsopko

Copy link
Copy Markdown
Author

For anyone who lands here needing this: the branch is maintained at https://github.com/jasonsopko/electrs/tree/blake2b (0.10.10 plus header v2 parsing, hashing and storage). It has run on a Knots mainnet node since the fork block, 961640, and on testnet4. For pruned nodes, paulscode/electrs-pruned carries the same support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants