Skip to content

Block hash commits to fat_pointer_to_bft_block — standard stratum ASICs cannot mine (100% DifficultyFilter rejection) #44

Description

@hyphae-bot

Summary

Crosslink's PoW block hash is computed as sha256d(header ‖ solution_varint ‖ solution ‖ fat_pointer_to_bft_block) — the BFT fat pointer is inside the hash preimage. Standard Equihash stratum miners (Antminer Z11/Z15 etc.) compute sha256d(header ‖ solution) in firmware and cannot be taught about the fat pointer. The hash an ASIC checks against the target is therefore a different number than the hash the node validates, so every ASIC "block find" is effectively a random 256-bit value vs. the real target → ~100% rejection with DifficultyFilter.

Reproduction (byte-exact, any accepted block)

Using accepted block 235728 (getblock "235728" 0, testnet CLT0, s2v9 + PR29/42):

hash preimage sha256d (displayed byte order) matches block hash?
header(140) ‖ solsize ‖ solution 0d56cb86... ❌ (this is what stratum hardware computes)
header(140) ‖ solsize ‖ solution ‖ fat_pointer 007befd4cf9fc519acda09bc09813b072f610761a0dcbea6dee99ed75aa705a9 ✅ exact match

(fat pointer parsed as: 44-byte vote prefix ‖ u16 LE sig count ‖ N × (32-byte pub_key ‖ 64-byte vote_signature))

Observed failure

Z11 → patched s-nomp (fat-pointer-aware block serialization) → submitblock. Shares that clear the stratum target are submitted and all rejected:

INFO zebra_rpc::methods: submit block failed verification
error=Ok(Block { source: Block { source: DifficultyFilter(Height(235877),
block::Hash("24a47a1b05a466bba494460439f0eb56a5c060949e841f8d9dcc6f46d15375b0"),
ExpandedDifficulty("00ba670000000000000000000000000000000000000000000000000000000000"), ...

The submitted blocks deserialize fine (fat pointer serialization is correct); they fail purely on the difficulty check because the true hash was never the thing the miner was grinding against the target.

Related

  • This same property explains part of the internal miner's stale-submit rejections (Miner: reject stale internal solver submissions #39 territory): the fat pointer changes with BFT state between template and submit, which changes the block hash and thus whether it still meets the target.

Suggested protocol-level fix

Commit the fat pointer inside the hashed 140-byte header instead of appending it to the hash preimage — e.g. fold a hash of fat_pointer_to_bft_block into hashBlockCommitments. Then standard stratum firmware grinds over a header that already commits to the BFT data, and off-the-shelf Equihash ASICs work unmodified.

Workaround we're running (pool-side)

Patched s-nomp to recompute the TRUE hash (sha256d(header‖sol‖fp)) for every share and only submitblock when that clears the network target ("lottery mode"). This stops the invalid submissions and does produce genuinely valid blocks at low network difficulty, but wastes almost all of the ASIC's hashrate — it's a stopgap, not a fix. Happy to share the patch and the hash-verification test script.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions