Skip to content

coinbaser: Enforce the sigop limit on payout outputs and count the BLAKE2b header in the coinbase weight limit - #24

Merged
luke-jr merged 2 commits into
CONVOYMining:masterfrom
iohzrd:coinbase-yuge
Oct 8, 2026
Merged

luke-jr merged 2 commits into
CONVOYMining:masterfrom
iohzrd:coinbase-yuge

Conversation

@iohzrd

@iohzrd iohzrd commented Oct 5, 2026 •

Copy link
Copy Markdown

Replaces #10, whose head branch was my fork's master. Reduced to the two changes CONVOY master does not have:

  • The per-miner class change from 40cf813 is dropped. 4d0a045 already serves every miner COINBASE_TYPE_YUGE, and datum_stratum_coinbase_index keeps its miner argument for per-miner selection later.
  • c031568 is dropped: it removed fingerprinting and classes 1, 2, 3 and 5, which luke-jr asked to keep on stratum: Blake payout path + rebase of open hardening onto #10 #15, and its YUGE (32000 bytes) and output-count (1024) increases depend on that removal.

Rebased onto 08123fc. The Tested ACKs on #10 were for 40cf813 and 7491a50. 993e261 is 40cf813's datum_coinbaser.c and datum_coinbaser_tests.c changes, with sigops now counted per script (below). 157500e is 7491a50 unchanged.

993e261: Enforce the template sigop limit on coinbaser outputs

Every miner is served COINBASE_TYPE_YUGE since 4d0a045, so a split can put hundreds of outputs in the coinbase, and the block's sigop limit has to be enforced on them. The budget is the template's sigoplimit minus the sigop cost of its transactions and of the pool output. Each output is charged datum_script_sigop_cost of its script: Bitcoin's legacy count (GetSigOpCount(false)) times 4. That counts OP_CHECKSIG and OP_CHECKSIGVERIFY as 1 and OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY as 20, skips pushed data, and stops at a push that runs past the end. The coinbaser parser stores it in available_coinbase_outputs[].sigops; before, it charged 4 only for a script starting with OP_DUP. The pool output is charged the same way. Tests cover bare P2PK (4), bare multisig (80), the VERIFY forms, opcode bytes inside pushed data, and truncated pushes. The check is applied in both passes of generate_coinbase_txns_for_stratum_job_subtypebysize, so the output count written to the varint matches the outputs written.

157500e: Coinbase size accounting for BLAKE2b blocks

  • datum_stratum_coinbase_fit_to_template reserved 340 weight units for the header and tx count, which assumes an 80-byte SHA256d header. It now uses the 164-byte BLAKE2b header plus the 5-byte count.
  • The coinbase's static byte count goes from 119 to 124. The old value was 3 to 5 bytes under the real transaction size, so a coinbase built to fill the template's remaining room could exceed the block weight limit by up to 20 WU.

Each commit builds with -Wall -Werror and passes --test. Merges without conflicts with each open PR that merges with master: #2, #3, #4, #6, #9, #11, #12, #13, #18, #20, #21, #26 and #27.

@iohzrd
iohzrd force-pushed the coinbase-yuge branch 2 times, most recently from ebabaeb to 76d748e Compare October 5, 2026 23:08
@iohzrd iohzrd changed the title stratum: Serve every miner the largest coinbase class on BLAKE2b work coinbaser: Enforce the sigop limit on payout outputs and count the BLAKE2b header in the coinbase weight limit Oct 5, 2026
@luke-jr
luke-jr requested a balanced review from Copilot October 6, 2026 16:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The sigop heuristic misses valid scripts such as bare P2PK and multisig, allowing invalid over-limit blocks.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Updates coinbase construction to respect block weight and sigop limits.

Changes:

  • Accounts for the 164-byte BLAKE2b header and corrected coinbase size.
  • Adds payout-output sigop budgeting and tests.
File Description
src/​datum_coinbaser.c Enforces limits during coinbase generation.
src/​datum_coinbaser_tests.c Tests weight and sigop accounting.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/datum_coinbaser.c Outdated
Comment on lines +213 to +214
// parser: 4 for a script whose first byte is OP_DUP (0x76, P2PKH) and 0
// for every other script. The pool output is charged the same way. An

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 993e261. datum_script_sigop_cost takes the legacy count the way GetSigOpCount(false) does (OP_CHECKSIG and OP_CHECKSIGVERIFY 1, OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY 20, pushed data skipped, stop at a truncated push) and multiplies it by 4. It replaces the OP_DUP first-byte check for dictated outputs in datum_coinbaser_v2_parse and for the pool output in generate_coinbase_txns_for_stratum_job_subtypebysize. datum_script_sigop_cost_tests covers bare P2PK (4) and bare multisig (80); datum_coinbaser_parse_sigops_tests and the bare P2PK pool case in datum_blake2b_coinbase_sigops_tests cover both call sites.

@luke-jr

luke-jr commented Oct 8, 2026

Copy link
Copy Markdown

Merges without conflicts with each open PR that merges with master:

Please don't list PRs like this

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