<p>From the <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/script.h#L200" rel="nofollow noreferrer">source code</a>:</p>

<blockquote>
  <p>Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as they are not used in a subsequent numeric operation). CScriptNum enforces those semantics by storing results as an int64 and allowing out-of-range values to be returned as a vector of bytes but throwing an exception if arithmetic is done or the result is interpreted as an integer.</p>
</blockquote>

<p>This does not explain why overflowing is allowed, but I guess this has to do with preventing errors (say, 3 billion + 3 billion resulting in a negative number).</p>

<p>As for the 4 byte limitation, I assume this is for safety. If there was no limitation, then because CScriptNum stores numbers as signed int64_t values, overflowing that limit (not the stack item overflow described in the previous paragraph) would result in <a href="https://stackoverflow.com/questions/18195715/why-is-unsigned-integer-overflow-defined-behavior-but-signed-integer-overflow-is">undefined behavior</a> according to the C standard. This is bad practice in general, but <strong>very bad</strong> in consensus-critical code. Most nodes run x86 Intel processors, but could you imagine how deeply in trouble we would be if a transaction was valid on Raspberry Pi based nodes and invalid on miner nodes, or valid locally on your smartphone and not on the network? All kinds of bad stuff would happen: hard forks, double spends, you name it.</p>

<p>You could also have problems with very large numbers being added to increase their size past the 520 byte push limit, then hashed repeatedly to consume as much CPU time as possible, resulting in a DoS attack.</p>

CC BY-SA 3.0
2016-11-22T15:29:17.303Z
2016-11-22T15:34:40.500Z
2016-11-22T15:34:40.500Z
maservant
<p>The <a href="https://en.bitcoin.it/wiki/Script" rel="nofollow noreferrer">Bitcoin wiki script page</a> says that:</p>
<blockquote>
<p>Arithmetic inputs are limited to signed 32-bit integers, but may overflow their output.</p>
<p>If any input value for any of these commands is longer than 4 bytes, the script must abort and fail.</p>
</blockquote>
<p>Does anyone know the reason behind this limitation? Why are arithmetic opcodes limited to 4 bytes?</p>

<script>
Why are arithmetic script opcodes limited to 4 byte operands?
cpsola
# Why are arithmetic script opcodes limited to 4 byte operands?

(Asked by: username_0 on 2016-11-22)

The [Bitcoin wiki script page](https://en.bitcoin.it/wiki/Script) says that:

> Arithmetic inputs are limited to signed 32-bit integers, but may overflow their output.
>
> If any input value for any of these commands is longer than 4 bytes, the script must abort and fail.

Does anyone know the reason behind this limitation? Why are arithmetic opcodes limited to 4 bytes?

**Tags:** script


---

## 1 answers

### Answer by username_1 on 2016-11-22. Score: 2 | Accepted answer

From the [source code](https://github.com/bitcoin/bitcoin/blob/master/src/script/script.h#L200):

> Numeric opcodes (OP\_1ADD, etc) are restricted to operating on 4-byte integers. The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as they are not used in a subsequent numeric operation). CScriptNum enforces those semantics by storing results as an int64 and allowing out-of-range values to be returned as a vector of bytes but throwing an exception if arithmetic is done or the result is interpreted as an integer.

This does not explain why overflowing is allowed, but I guess this has to do with preventing errors (say, 3 billion + 3 billion resulting in a negative number).

As for the 4 byte limitation, I assume this is for safety. If there was no limitation, then because CScriptNum stores numbers as signed int64\_t values, overflowing that limit (not the stack item overflow described in the previous paragraph) would result in [undefined behavior](https://stackoverflow.com/questions/18195715/why-is-unsigned-integer-overflow-defined-behavior-but-signed-integer-overflow-is) according to the C standard. This is bad practice in general, but **very bad** in consensus-critical code. Most nodes run x86 Intel processors, but could you imagine how deeply in trouble we would be if a transaction was valid on Raspberry Pi based nodes and invalid on miner nodes, or valid locally on your smartphone and not on the network? All kinds of bad stuff would happen: hard forks, double spends, you name it.

You could also have problems with very large numbers being added to increase their size past the 520 byte push limit, then hashed repeatedly to consume as much CPU time as possible, resulting in a DoS attack.


---

