Skip to content

script: bound how many operations and stack entries a script may use - #57

Merged
Bitflash-sh merged 1 commit into
mainfrom
consensus-limits
Jul 30, 2026
Merged

script: bound how many operations and stack entries a script may use#57
Bitflash-sh merged 1 commit into
mainfrom
consensus-limits

Conversation

@Bitflash-sh

Copy link
Copy Markdown
Owner

Part of the post-0.1.0 hardening. #15 disabled the unbounded opcodes and capped a single pushed element at 520 bytes; it did not add a ceiling on how many items there can be.

Without one, a script pays for itself once, in bytes, and then multiplies. 520 bytes per stack entry means a script of N bytes made almost entirely of OP_DUP occupies roughly 520N in memory, on every node that validates it.

The limits

  • 201 operations per script, counted outside the fExec test so the cost of a script cannot depend on which branch a signature happens to take. Pushes are exempt — already bounded by the script length and by MAX_SCRIPT_ELEMENT_SIZE.
  • 1000 entries across both stacks together, counted together because OP_TOALTSTACK would otherwise move the problem rather than solve it.

Both tighten validation, so a node that does not upgrade accepts a superset of what this one accepts and is not stranded.

Verified against the live chain

A node with these rules synced all 3910 blocks from genesis and accepted every one. Nothing in use relies on scripts these limits would reject.

BIP30 was pulled out of this branch

It was meant to ship here too. Syncing from genesis with the check in place rejected a real block at height 859, so it stays out until the cause is fixed. Details and numbers in the issue that follows.

v1.2.1 disabled the unbounded opcodes and capped a single pushed element at
520 bytes. What it did not add was a ceiling on how many items there can be,
so a script still pays for itself once, in bytes, and then multiplies: 520
bytes per stack entry means a script of N bytes made almost entirely of
OP_DUP occupies roughly 520N in memory, on every node that validates it.

Two limits, both from Bitcoin:

  - at most 201 operations per script, counted outside the fExec test so
    the cost of a script cannot depend on which branch a signature happens
    to take. Pushes are exempt, being already bounded by the script length
    and by MAX_SCRIPT_ELEMENT_SIZE.
  - at most 1000 entries across both stacks together, counted together
    because OP_TOALTSTACK would otherwise move the problem rather than
    solve it.

This tightens validation, so a node that does not upgrade accepts a
superset of what this one accepts and is not stranded.

Verified against the live chain: a node with these rules synced all 3910
blocks from genesis and accepted every one, so nothing in use relies on
scripts these limits would reject.
@Bitflash-sh
Bitflash-sh merged commit 4d78992 into main Jul 30, 2026
@Bitflash-sh
Bitflash-sh deleted the consensus-limits branch July 30, 2026 21:22
@Bitflash-sh Bitflash-sh mentioned this pull request Jul 31, 2026
Bitflash-sh added a commit that referenced this pull request Jul 31, 2026
Six changes since 1.2.7, and the reason not to sit on this is #58:
coinbase transactions were not unique, two of them overwrote older ones
on the main chain, and 100 BTF stopped being reachable. Nothing in how
they were built had changed since, so it could happen again at any time.
The height now goes into the coinbase on both paths that build one
(#59, #60), which makes a repeat impossible without any coordination.

Also in: a node now notices a peer it can no longer hear and stays
audible to peers that check the same way (#55); it announces its height
in the handshake and says out loud when it falls behind the network
(#56); script evaluation has ceilings on operation count and stack depth
(#57); the tail of the chain is verified at startup and a bad tip is
backed out of instead of being mined on (#61); and the wallet now
believes the chain about what it has already spent, which is what a
restored backup gets wrong (#62).
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.

1 participant