BIP301 · Blind merged mining

BIP301 Blind Merged Mining

BIP301 lets a Bitcoin miner sell the right to extend a sidechain without running that sidechain, validating it, or even knowing what is in the block being extended. It is an auction with one lot per sidechain per block — and the whole design turns on the fact that the winning bid must be countersigned in the coinbase.

Third of three. Drivechain Messages M1–M8 covers the wire format and the coinbase / peer-to-peer split; BIP300 Hashrate Escrow covers the voting machinery underneath. This page is about the mining half and its economics.

What "blind" actually buys

A merge-mining scheme normally requires the mainchain miner to run the auxiliary chain: build its blocks, validate its transactions, hold its state. BIP301 removes all of that. The miner is handed a 32-byte hash and asked to commit to it, and is paid to do so.

The miner therefore cannot tell a valid sidechain block from an invalid one, and does not need to — sidechain nodes reject bad blocks on their own. What the miner sells is ordering and finality, not validation. That is what makes the scheme safe to offer to miners who have no interest in the sidechain at all, and it is why the commitment has to be structurally unforgeable rather than merely conventional.

The lot 1 per sidechain Per mainchain block. A second M7 for the same slot is a fatal block error.
The bid the tx fee An M8's bribe is simply the fee its transaction pays. There is no separate bribe output.
The cost to the miner 192 wu The M7 coinbase output: (8 + 1 + 39) × 4 weight units.

The handshake

%%{init: {"theme":"base","themeVariables":{"fontFamily":"IBM Plex Mono, monospace","fontSize":"13px","primaryColor":"#EDEFF3","primaryTextColor":"#15181D","primaryBorderColor":"#2B7A87","lineColor":"#5E6672","actorBkg":"#FFFFFF","actorBorder":"#5E6672","actorTextColor":"#15181D","signalColor":"#15181D","signalTextColor":"#15181D","noteBkgColor":"#E2F0F2","noteBorderColor":"#2B7A87","noteTextColor":"#15181D","sequenceNumberColor":"#FFFFFF"}}}%%
sequenceDiagram
    autonumber
    participant SC as Sidechain node
    participant Enf as Enforcer wallet
    participant Mem as Mainchain mempool
    participant Min as Miner with enforcer
    participant CB as Coinbase

    SC->>SC: snapshot mempool into a body, hash it as H*
    SC->>Enf: CreateBmmCriticalDataTransaction(S, H*, prev_tip)
    Enf-->>SC: refuse if prev_tip is stale
    Enf->>Mem: M8 broadcast, fee = bribe
    Min->>Min: accept M8, reserve 192 wu
    Min->>CB: append M7 (S, H*)
    Min->>Min: mine the block
    CB-->>SC: commitment seen
    SC->>SC: connect the snapshotted body
The body is snapshotted before the bid, not after. Whatever was in the sidechain mempool at step 1 is what gets connected at step 9 — so a transaction that arrives mid-auction waits for the next round, and dropping one from the mempool after bidding does not remove it from the block that may still land.
Expiry is structural
M8 carries prev_mainchain_block_hash
enforcer refuses to create it unless that equals the current tip
validator rejects it later unless it still does  // BmmRequestExpired

A bid is valid for exactly one mainchain block — the one building directly on the tip it named. When that tip is superseded the bid is dead on the wire, which is why a sidechain node issues a fresh M8 per mainchain block rather than leaving one standing.

The auction, and who can bid in it

Pending requests are keyed on (prev_mainchain_block_hash, sidechain_number). Every M8 sharing that key is competing for the same single lot, and the enforcer records the rest as conflicting when one is accepted. Two consequences follow, and they are the practically important ones:

Who your bribe is actually competing against

Not the mempool at large. A higher fee does not persuade a miner without an enforcer to help you — that miner has no code path that emits M7 and structurally cannot accept your bid at any price. Raising the bribe only matters when another enforcer-driven miner is choosing between your request and a rival's for the same slot.

On a chain where nobody mines with an enforcer, the clearing price is irrelevant: there are no bidders, and every block arrives with no commitment for your slot regardless of what you paid.

What the miner is weighing
gain = M8 fee
cost = 192 wu of coinbase  +  the M8's own block space

Against a full block the comparison is against the marginal fee-rate of what gets displaced, so a bribe is best read as a fee rate rather than an amount. Against an empty block almost any bribe clears. The default bribe in most sidechain implementations is set for the second case and loses badly in the first.

What a miner without an enforcer does with your M8

Nothing useful — but the precise behaviour is worth knowing, because the failure is silent from both sides.

%%{init: {"theme":"base","themeVariables":{"fontFamily":"IBM Plex Mono, monospace","fontSize":"13px","primaryColor":"#F8E9E2","primaryTextColor":"#15181D","primaryBorderColor":"#9C4221","lineColor":"#5E6672","secondaryColor":"#EDEFF3","tertiaryColor":"#E2F0F2"}}}%%
flowchart TB
    A["M8 relayed to every mainchain node"] --> B{"miner builds template
from an enforcer?"} B -->|no| C["M8 mined as an ordinary fee-paying tx"] C --> D["no M7 in coinbase"] D --> E["validator: NotAcceptedByMiners
non-fatal — block stays valid"] E --> F["sidechain does not advance
bribe is spent"] B -->|yes| G["M8 mined AND M7 appended"] G --> H["sidechain block connects"]
The block is not rejected. An M8 without its matching M7 raises NotAcceptedByMiners, but that error is explicitly non-fatal — the mainchain block stands, the transaction's fee is collected, and only the sidechain loses.
The three BMM refusals and what each one costs.
ConditionSeverityWhat happened
NotAcceptedByMiners non-fatal M8 in the block, no matching M7 in the coinbase. Block valid; bribe spent; sidechain unchanged.
BmmRequestExpired non-fatal M8's prev_mainchain_block_hash is not this block's parent. Checked even when no M7 context exists.
MultipleBmmBlocks fatal Two M7s for the same sidechain in one coinbase. The block is rejected outright — this is the rule that makes the lot singular.

Reading a stalled sidechain

A sidechain that will not advance produces a very specific log signature. Distinguishing its three causes takes one glance each:

INFO  attempt BMM: created TX: 436ed0e0…
WARN  confirm BMM: received new block without our BMM commitment
      side_hash=26817a96… main_height=996455 bmm_commitment=none
SymptomCauseCheck
bmm_commitment=none No enforcer-driven miner accepted anything for this slot Is the bid even in the mainchain mempool? getmempoolentry <txid>
A commitment appears, but for a different hash A rival M8 won the slot Compare the committed hash against your side_hash
No attempt BMM lines at all Nothing is asking — the node only bids once per mainchain block Is the mainchain tip moving? A stalled parent means no new bids

The third case is the one most often misread as a bug. A node makes at most one BMM attempt per mainchain block, so on a chain producing a block an hour, a silent BMM log is correct behaviour rather than a stuck miner.

Where BIP301 hands back to BIP300

Blind merged mining moves a sidechain forward; it never moves coins across the peg. Those are separate machines with separate trust:

QuestionAnswered byRequires
Which sidechain block comes next?M7 + M8One miner, paid, per block
May this sidechain exist at all?M1 + M2A sustained miner vote
May these coins leave it?M3 + M4M6A sustained miner vote

A miner selling BMM is selling ordering only. Nothing about accepting an M7 approves a withdrawal, and a sidechain can be mined for months by miners who never vote on its bundles — the two are deliberately unrelated.