Skip to content

Commit aadcb32

Browse files
authored
Merge pull request #163 from plebhash/2025-10-24-adapt-coinbase-transaction-constraints
clarify `CoinbaseOutputConstraints`
2 parents fb9cab8 + 6bca4aa commit aadcb32

File tree

1 file changed

+71
-9
lines changed

1 file changed

+71
-9
lines changed

07-Template-Distribution-Protocol.md

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,84 @@ Thereafter, the server SHOULD push new block templates to the client whenever th
1010

1111
Template Providers MUST attempt to broadcast blocks which are mined using work they provided, and thus MUST track the work which they provided to clients.
1212

13+
When crafting a template, in order to avoid creating an invalid, oversized block, the Template Provider MUST reserve appropriate blockspace and sigops for:
14+
- the block header: 80 bytes, or 320 weight units
15+
- the block transaction count: 3 bytes (which in terms of `CompactSize` is worst case for minimally sized transactions in a block), or 12 weight units
16+
- the serialized coinbase transaction: which has fixed-sized and variable-sized fields, see definition of [`CoinbaseOutputConstraints`](#71-coinbaseoutputconstraints-client---server) below
17+
1318
## 7.1 `CoinbaseOutputConstraints` (Client -> Server)
1419

15-
Ultimately, the pool is responsible for adding coinbase transaction outputs for payouts and other uses, and thus the Template Provider will need to consider this additional block size, and sigops when selecting transactions for inclusion in a block (to not create an invalid, oversized block).
16-
Thus, this message is used to indicate that some additional space and sigops in the block/coinbase transaction be reserved for the pool’s use (while always assuming the pool will use the entirety of available coinbase space and sigops).
20+
Here's a table with all fields of a Coinbase Transaction that have fixed size:
21+
22+
| field name | size | weight factor | weight |
23+
|---------------------------------------------|----------------------|---------------|--------|
24+
| `version` | 4 bytes | 4 WU/byte | 16 WU |
25+
| `marker` + `flag` | 2 bytes (if SegWit) | 1 WU/byte | 2 WU |
26+
| `input count` (always 1) | 1 byte | 4 WU/byte | 4 WU |
27+
| `prev txid` | 32 bytes | 4 WU/byte | 128 WU |
28+
| `input index` | 4 bytes | 4 WU/byte | 16 WU |
29+
| `scriptSig length` (100 bytes max) | 1 byte | 4 WU/byte | 4 WU |
30+
| `input sequence` | 4 bytes | 4 WU/byte | 16 WU |
31+
| `witness stack size` (always 1) | 1 byte (if SegWit) | 1 WU/byte | 1 WU |
32+
| `size of witness element` (always 32 bytes) | 1 byte (if SegWit) | 1 WU/byte | 1 WU |
33+
| `witness reserved value` | 32 bytes (if SegWit) | 1 WU/byte | 32 WU |
34+
| `locktime` | 4 bytes | 4 WU/byte | 16 WU |
35+
36+
So a Template Provider MUST reserve 236 weight units for the fixed-size fields in case of a SegWit block, or 200 weight units in the unlikely case of a legacy block. Meanwhile, the following fields of a Coinbase Transaction have variable size:
37+
38+
| field name | size | weight factor | weight |
39+
|----------------|---------------|---------------|------------|
40+
| `scriptSig` | 100 bytes max | 4 WU/byte | 400 WU max |
41+
| `output count` | 3 bytes max | 4 WU/byte | 12 WU max |
42+
| `outputs` | no limit | 4 WU/byte | no limit |
43+
44+
Note: while `output count` is `CompactSize`, we can only fit ~110k minimally sized outputs into a block, so 3 bytes is the worst case value here.
45+
46+
So a Template Provider MUST also reserve:
47+
- the worst-case 400 weight units for `scriptSig` field
48+
- the worst-case 12 weight units for `output count` field
49+
- 188 weight units for witness commitment output (if SegWit)
50+
51+
But ultimately, the Pool (or JDC, in case of Job Declaration) is responsible for adding coinbase transaction outputs for payouts and other uses, and thus the Template Provider will need to consider this additional block size, and sigops when selecting transactions for inclusion in a block.
52+
53+
Thus, the `CoinbaseOutputConstraints` message is used to indicate that some additional space and sigops in the block/coinbase transaction be reserved for the Pool or JDC use (while always assuming the entirety of available coinbase space and sigops will be used).
54+
55+
JDC MUST discover the maximum serialized size of the additional outputs and sigops which will be added by the Pool(s) it intends to use this work with (via `AllocateMiningJobToken.Success`). It then MUST communicate it to the Template Provider via `CoinbaseOutputConstraints`.
1756

18-
The Job Declarator MUST discover the maximum serialized size of the additional outputs and sigops which will be added by the pool(s) it intends to use this work.
19-
It then MUST communicate it to the Template Provider via this message.
2057
The Template Provider MUST NOT provide `NewTemplate` messages which would represent consensus-invalid blocks once this additional size and sigops — along with a maximally-sized (100 byte) coinbase script field — is added.
21-
Further, the Template Provider MUST consider the maximum additional bytes required in the output count variable-length integer in the coinbase transaction when complying with the size limits.
22-
Current sigops limit per block in bitcoin is 80_000. We are not aware of any use cases where
23-
coinbase have more the 65_535 so coinbase_output_max_sigops is an U16. Note that taproot outputs consume 0 sigops.
58+
59+
Current sigops limit per block in bitcoin is `80_000`. We are not aware of any use cases where a coinbase transaction has more than `65_535` so `coinbase_output_max_sigops` is an `U16`. Note that taproot outputs consume `0` sigops.
2460

2561
| Field Name | Data Type | Description |
2662
| ------------------------------------- | --------- | ----------------------------------------------------------------------------------------------- |
27-
| coinbase_output_max_additional_size | U32 | The maximum additional serialized bytes which the pool will add in coinbase transaction outputs |
28-
| coinbase_output_max_additional_sigops | U16 | The maximum additional sigops which the pool will add in coinbase transaction outputs |
63+
| coinbase_output_max_additional_size | U32 | The maximum additional serialized bytes which Pool or JDC will add in coinbase transaction outputs |
64+
| coinbase_output_max_additional_sigops | U16 | The maximum additional sigops which Pool or JDC will add in coinbase transaction outputs |
65+
66+
Below are the formulas that summarize the rationale around reserving blockspace presented above. In addition to reserving `coinbase_output_max_additional_sigops` sigops, the Template Provider MUST reserve the following weight unit values.
67+
68+
For SegWit blocks:
69+
70+
- block header: 320 weight units
71+
- block tx count: 12 weight units
72+
- coinbase tx fixed-size fields: 236 weight units
73+
- coinbase tx `scriptSig`: 400 weight units
74+
- coinbase tx `output count`: 12 weight units
75+
- coinbase tx witness commitment output: 188 weight units
76+
- coinbase tx outputs added by Pool or JDC: 4*`coinbase_output_max_additional_size` weight units
77+
78+
total: 1168 + 4*`coinbase_output_max_additional_size` weight units
79+
80+
For legacy blocks:
81+
- block header: 320 weight units
82+
- block tx count: 12 weight units
83+
- coinbase tx fixed-size fields: 200 weight units
84+
- coinbase tx `scriptSig`: 400 weight units
85+
- coinbase tx `output count`: 12 weight units
86+
- coinbase tx outputs added by Pool or JDC: 4*`coinbase_output_max_additional_size` weight units
87+
88+
total: 944 + 4*`coinbase_output_max_additional_size` weight units
89+
90+
Please note that Bitcoin Core establishes a floor value of 2000 weight units.
2991

3092
## 7.2 `NewTemplate` (Server -> Client)
3193

0 commit comments

Comments
 (0)