B3PoW-Scratch Reference Verifier

A standalone Python script that replays the B3PoW-Scratch v1.1.1 consensus vectors through the byte-for-byte Python reference implementation. Requires no running node and no C++ build — just Python and the official blake3 binding.

Script: verify-b3pow.py Runtime: ~2 seconds (vectors only) Status: PASS

1. Overview

Block identity hashes (block hash, txid, merkle tree) on b3chain still use double SHA-256, identical to Bitcoin Core. The proof-of-work hash is the only consensus-critical hash that differs — it is B3PoW-Scratch v1.1.1, a memory-hard BLAKE3 variant that walks a 1 MB scratchpad keyed by the previous block hash:

PoW_hash = b3pow_scratch( serialize(block_header), init_scratchpad(prev_block_hash) )

where the 80-byte header serialisation is:
  nVersion       (4 bytes, int32, little-endian)
  hashPrevBlock  (32 bytes, uint256, little-endian)
  hashMerkleRoot (32 bytes, uint256, little-endian)
  nTime          (4 bytes, uint32, little-endian)
  nBits          (4 bytes, uint32, little-endian)
  nNonce         (4 bytes, uint32, little-endian)

and init_scratchpad expands prev_block_hash into a 1 MiB pad via
BLAKE3-XOF; b3pow_scratch then runs 2048 outer iterations across
8 lanes (2 inner BLAKE3 rounds each) and folds the lane state into a
final 32-byte digest.

The verifier loads the canonical JSON vector set at src/test/data/b3pow_consensus_vectors.json and recomputes every entry through the Python reference at contrib/miner/b3miner-rtl/ref/b3pow_ref.py. The JSON file is what pins the C++ port to the Python reference; any change to the algorithm shows up as a parity mismatch in one of the C++ test_bitcoin runs.

The full algorithm spec is at contrib/miner/b3miner-rtl/SPEC.md.

2. Prerequisites

OS
Linux, macOS, or WSL2
Python
3.10+
Dependency
pip3 install blake3
Reference module
ships with the repo at contrib/miner/b3miner-rtl/ref/

3. Run it

git clone https://github.com/b3chain/b3chain.git
cd b3chain
pip3 install blake3
python3 contrib/testing/verify-b3pow.py

The old entry point verify-blake3-pow.py is now a thin deprecation shim that forwards to verify-b3pow.py and prints a one-line warning. It will be removed in the next release.

4. Expected output

============================================================
 B3Chain B3PoW-Scratch v1.1.1 Verification
============================================================

[1/3] b3pow_ref self-check
  PASS: SPEC_VERSION
  PASS: b3pow_ref deterministic (zero-header)

[2/3] B3PoW-Scratch consensus vectors
  Loaded schema_version=1, spec_version=0x00010101
  PASS: spec_version matches b3pow_ref
  PASS: genesis_mainnet_template: b3pow_scratch hash
  PASS: genesis_mainnet_template: pow_hash <= target
  PASS: genesis_regtest: b3pow_scratch hash
  PASS: genesis_regtest: pow_hash <= target
  PASS: mainnet_target_loose_pass: b3pow_scratch hash
  PASS: mainnet_target_loose_pass: pow_hash <= target
  PASS: mainnet_target_tight_fail: b3pow_scratch hash
  PASS: mainnet_target_tight_fail: pow_hash <= target
  PASS: nontrivial_prev: b3pow_scratch hash
  PASS: nontrivial_prev: pow_hash <= target
  PASS: cache_pair_nonce_0: b3pow_scratch hash
  PASS: cache_pair_nonce_0: pow_hash <= target
  PASS: cache_pair_nonce_1: b3pow_scratch hash
  PASS: cache_pair_nonce_1: pow_hash <= target

[3/3] Live block verification
  SKIP: no --rpc-port specified

============================================================
 RESULTS: N/N passed, 0 failed
============================================================
 All tests passed!

5. With a live node (optional)

python3 contrib/testing/verify-b3pow.py --rpc-port=18545

Connects to a running b3chain regtest / testnet node, fetches a handful of representative headers, rebuilds each 80-byte header plus its prev_block_hash, recomputes the B3PoW-Scratch hash via b3pow_ref, and asserts that it is below the node-reported target. Pads are cached by prev_block_hash so siblings of the same parent reuse the 1 MB scratchpad (same optimisation as the C++ b3pow::Cache).

6. Common pitfalls

  • Forgetting prev_block_hash. B3PoW-Scratch's first byte of input is the parent-block hash, used to seed the scratchpad. A reference miner that hashes only the 80-byte header will never agree with the chain.
  • Using hashlib.blake2b by mistake — b3chain uses BLAKE3, a different (faster, parallel) algorithm. The blake3 Python package is the official binding.
  • Forgetting little-endian byte order for header fields. The verifier prints the bytes it serialised so you can diff them against your own.
  • Skipping the consensus vectors. If you only test the inner BLAKE3 primitive you will miss any divergence in the scratchpad walk, the lane mix function, or the finaliser.

7. Source links