B3PoW-Scratch Consensus Vectors

Canonical (header, prev_block_hash)pow_hash pairs that pin the C++ port to the Python reference. Use these to validate any independent B3PoW-Scratch v1.1.1 implementation — alternative client, hardware miner, or FPGA / RTL port.

1. Algorithm under test

Algorithm
B3PoW-Scratch v1.1.1 (post-F-1, live since genesis)
SPEC_VERSION
0x00010101
FPGA REG_ID magic
0xB3110002 (build 0002)
Scratchpad size
1 048 576 bytes (1 MiB) per parent
Scratchpad blocks
16 384 total (8 lanes × 2 048 blocks × 64-byte block)
Lanes
8 (cross-lane diffusion via LANE_SHUFFLE = [1,6,3,0,5,2,7,4])
Outer iterations
2048
Inner BLAKE3 rounds / iter
2
Inner round function
BLAKE3
Verifier wall-clock budget
50 ms (consensus parameter)
F-1 fix
ITER_MUL[7] = 0x6E5C6F88AA5BDA77 (made pairwise distinct from ITER_MUL[1]; see B3POW-51-ATTACK-ANALYSIS.md)
Spec
contrib/miner/b3miner-rtl/SPEC.md

2. Vector set

The complete machine-readable set lives at src/test/data/b3pow_consensus_vectors.json; the table below summarises the entries. All hex values are big-endian display order (block-explorer style).

Name Purpose prev_block_hash (hex) expected pow_hash (hex)
genesis_mainnet_template locks the JSON schema against the mainnet genesis-style header (post-F-6, nBits = 0x1d7fffff) 000...000 50c8c8def866529c7637868d175ec80dafcc59ed5a375abb8b2fdb5b53a15c77
genesis_regtest regtest powLimit is loose (0x207fffff) so any hash passes 000...000 1822743d5bfed8eeac80117b4536e116597c29453b21582950c5f0357b9ffe63
mainnet_target_loose_pass mainnet powLimit (0x1d7fffff, post-F-6) with the loose target 000...000 5c889fa7c5be894c135b4c1348cddb14beeef2dc5295613afc6ba68fe9ee9c37
mainnet_target_tight_fail synthetic target=1 — expected to fail PoW with overwhelming probability 000...000 5c889fa7c5be894c135b4c1348cddb14beeef2dc5295613afc6ba68fe9ee9c37
nontrivial_prev same header as mainnet_target_loose_pass, non-zero prev_block_hash: pow_hash MUST differ deadbeef...3210 4d82fe20390d36016f2ee9a0cfd447e92cac70528047f653db719862ed3931bf
cache_pair_nonce_0 first member of a same-parent pair, exercises the LRU scratchpad cache (H-1.2) 0102...1f20 c9b61079e2e50c4dacc51af107043d4a0b47c84945bc8d6d1df6b801b6430313
cache_pair_nonce_1 second member of the cache pair (nonce=1) — C++ test asserts this is served from the cache after the first 0102...1f20 fa6993083b67ebb0a4876f65d94ded886fb75e46cab7f4283ca7c13abbf89e18

The two cache_pair_* entries deliberately share the same prev_block_hash so the C++ unit tests in b3pow_cache_tests.cpp can prove the LRU is doing real work.

3. Header serialisation

Same 80-byte wire format as Bitcoin Core, little-endian fields, used by all entries above.

FieldValue
nVersion4 bytes, int32 LE
hashPrevBlock32 bytes, uint256 LE (seeds the 1 MB scratchpad)
hashMerkleRoot32 bytes, uint256 LE
nTimeuint32 LE
nBitscompact target (e.g. 0x1d7fffff on mainnet, post-F-6; 0x207fffff on regtest)
nNonceuint32 LE; the miner varies this

4. How to use these vectors

  1. Decode the entry: header_hex (80 bytes), prev_block_hash_hex (32 bytes), nbits_hex.
  2. Initialise the scratchpad from prev_block_hash (the algorithm seeds an XOF from that 32-byte value and fills the 1 MiB pad).
  3. Run B3PoW-Scratch over the 80-byte header with the freshly initialised pad; obtain the 32-byte pow_hash.
  4. Compare to expected_pow_hash_hex — must match byte-for-byte.
  5. Optionally check pow_hash < target(nBits); compare to expected_check_pow for parity with the C++ CheckProofOfWork.

5. Source files