<p>The actual encodings of the numbers 1-16 are <code>0x51</code>, <code>0x52</code>, etc. This is because the numbers 1-16 are special in Bitcoin script and have their own explicit opcodes. OP_1 is <code>0x51</code>, OP_2 is <code>0x52</code>, etc. The correct way to write numbers with their own opcodes is to use those opcodes instead of using a pushdata opcode followed by the number.</p>

CC BY-SA 4.0
2020-07-20T16:24:06.237Z
2020-07-20T16:24:06.237Z
Ava Chow
<p><a href="https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki" rel="nofollow noreferrer">BIP-34</a> claims that in coinbase transactions, the scriptSig should contain the block height. It says the format of this is &quot;serialized CScript&quot;, i.e. a byte indicating the length of the number (<code>n</code>), and then <code>n</code> bytes in little-endian format.</p>
<p>This works if you look at e.g. the most recent block as of this writing—<a href="https://blockstream.info/block/0000000000000000000bec007763e166f8ea399f494e6b196d3eea79c526ed0a" rel="nofollow noreferrer">block 640037</a>—whose coinbase scriptSig begins with these 4 bytes: <code>0x0325c409</code>. <code>0x03</code> indicates the length, and then we have <code>(0x25=37 * 256^0) + (0xc4=196 * 256^1) + (0x09=9 * 256^2)</code>, or <code>37 + 50176 + 589824 = 640037</code>.</p>
<p>For obvious reasons mainnet and testnet will never need to encode heights 1-16 in their coinbase. But regtest nodes will. When I run a fresh regtest node (<code>v0.19.1</code>) and generate a couple blocks, I get coinbase scriptSigs that look like this:</p>
<pre><code>height 1: 0x510101
height 2: 0x520101
...
height 16: 0x600101
</code></pre>
<p>Clearly it's not serialized CScript, at least in the format described in BIP-34. If it were, those first bytes would indicate data lengths of 81, 82, and 96 respectively, clearly ridiculous. The actual encodings of 1, 2, and 16 in serialized CScript are <code>0x0101</code>, <code>0x0102</code>, and <code>0x0110</code>. It looks to me like the format is <code>height+80</code> followed by <code>0x0101</code>. And for some reason this only persists for the first 16 blocks, as 17's scriptSig is <code>0x01110101</code>.</p>
<p>I tried looking through the bitcoin source code, but I don't write much C++ so it's hard to tell what's going on. No documentation—in the source (as far as I can tell) or the <a href="https://github.com/bitcoin/bitcoin/pull/1526" rel="nofollow noreferrer">PR for BIP-34</a> or in the BIP itself seems to indicate that heights 1-16 would have a different format from every other height.</p>
<p>Why is this happening?</p>

<script><coinbase-transaction><height>
Why is the data format for block height in coinbase scriptSigs inconsistent for heights 1-16?
henryperson
# Why is the data format for block height in coinbase scriptSigs inconsistent for heights 1-16?

(Asked by: username_0 on 2020-07-20)

[BIP-34](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki) claims that in coinbase transactions, the scriptSig should contain the block height. It says the format of this is "serialized CScript", i.e. a byte indicating the length of the number (`n`), and then `n` bytes in little-endian format.

This works if you look at e.g. the most recent block as of this writing—[block 640037](https://blockstream.info/block/0000000000000000000bec007763e166f8ea399f494e6b196d3eea79c526ed0a)—whose coinbase scriptSig begins with these 4 bytes: `0x0325c409`. `0x03` indicates the length, and then we have `(0x25=37 * 256^0) + (0xc4=196 * 256^1) + (0x09=9 * 256^2)`, or `37 + 50176 + 589824 = 640037`.

For obvious reasons mainnet and testnet will never need to encode heights 1-16 in their coinbase. But regtest nodes will. When I run a fresh regtest node (`v0.19.1`) and generate a couple blocks, I get coinbase scriptSigs that look like this:

```
height 1: 0x510101
height 2: 0x520101
...
height 16: 0x600101

```

Clearly it's not serialized CScript, at least in the format described in BIP-34. If it were, those first bytes would indicate data lengths of 81, 82, and 96 respectively, clearly ridiculous. The actual encodings of 1, 2, and 16 in serialized CScript are `0x0101`, `0x0102`, and `0x0110`. It looks to me like the format is `height+80` followed by `0x0101`. And for some reason this only persists for the first 16 blocks, as 17's scriptSig is `0x01110101`.

I tried looking through the bitcoin source code, but I don't write much C++ so it's hard to tell what's going on. No documentation—in the source (as far as I can tell) or the [PR for BIP-34](https://github.com/bitcoin/bitcoin/pull/1526) or in the BIP itself seems to indicate that heights 1-16 would have a different format from every other height.

Why is this happening?

**Tags:** script, coinbase-transaction, height


---

## 1 answers

### Answer by username_1 on 2020-07-20. Score: 4 | Accepted answer

The actual encodings of the numbers 1-16 are `0x51`, `0x52`, etc. This is because the numbers 1-16 are special in Bitcoin script and have their own explicit opcodes. OP\_1 is `0x51`, OP\_2 is `0x52`, etc. The correct way to write numbers with their own opcodes is to use those opcodes instead of using a pushdata opcode followed by the number.


---

