After chatting with other developers who are reviewing this CHIP, once people get the hang of Forth-style loops, they quickly notice the artificially heavy “cost” of each instruction vs. actual compute time.
The oldest snippet in the CHIP (from 2021) is actually the perfect example:
<0> <0>
OP_BEGIN // Loop (re)starts with index, value
OP_OVER OP_UTXOVALUE OP_ADD // Add UTXO value at index to total
OP_SWAP OP_1ADD OP_SWAP // Increment index
OP_OVER OP_TXINPUTCOUNT OP_EQUAL
OP_UNTIL // Loop until index equals the TX input count
OP_NIP // Drop index, leaving sum of UTXO values
This loop steps over each UTXO and sums up their values. Literally just adding small numbers in a tight loop that all of today’s node implementations power through many times faster than the same “cost” of e.g. hashing or signature checking.
However, the “Base Instruction Cost” of 100
means that every single pass over every single instruction – even unexecuted instructions inside OP_IF
/OP_ENDIF
blocks – costs nearly half of a SHA256 hash iteration.
In practice that means this chunk of bytecode only “pays for its own compute” up to ~10 UTXOs. Base instruction Cost absorbs almost all of the budget, with a tiny sliver taken by the addition itself.
Of course, this was a careful choice in the VM Limits upgrade: Rationale: Selection of Base Instruction Cost. In short: even if all of our review missed some specific performance issue before the May 2025 upgrade – in any one of the node implementations – the worst impact couldn’t magnify attacks by greater than 10x.
Since our measured safety margin was 10x to 100x, the base instruction cost of 100
was conservative enough to give us a complete, additional layer of protection – between 1x and 10x more conservative than the specific-costs layer – even if our review had missed a critical vulnerability.
Anyways, all this to say: I think the loops CHIP should also reduce Base Instruction Cost another level, from 100
to 10
, to be more inline with actual performance.
For context, note that BTC’s Taproot upgrade established an implicit Base Instruction Cost of 1
– meaning 100x lower than ours – such that performance issues are much more likely to become real DoS vectors, especially in alternative implementations (not to mention the technical debt that would be incurred to support loops or functions).
In our case, even though the 2025 upgrade is live and no further performance issues were found, I still think it’s wise to iterate slowly – lowering to a base instruction cost of 10
retains at least a 10x margin of safety over the BTC VM, and wouldn’t impact our current 10-100x margin of safety (see the benchmarks here – various fast-instruction-evaluation benchmarks on BCHN are so fast that none made the worst-cases graph; you’ll have to look at the CSVs.)
Why should the Loops CHIP lower Base Instruction Cost?
I want to note that “lowering base instruction cost” is very specific to the loops CHIP: it’s doesn’t really make sense unless you’re doing cheap, tight iteration, and the only way 99% of contract developers will encounter this unusual behavior is when using a simple loop to do something they think should be very cheap (and they’re right) – e.g. summing the value of more than 10 UTXOs.
In general, we don’t want tooling like CashScript or AlbaDsl to have to deal with this weird edge case (which would look like this), particularly since it’s primary, network-defensive purpose has passed.
On a more practical level, it’s also not reasonable to thoroughly benchmark a base instruction cost “lowering” without loops. With loops, we can simply benchmark that every single instruction inside a tight loop still costs much less than hashing (which again, is itself far, far faster than signature checking), and we’re literally doing that benchmarking this year: as part of the Loops CHIP.
I’m leaving the cost at 100
for now in Bitauth IDE’s 2026 testing preview, so you easily see for yourself how silly the limit is with various kinds of fast loops.
Sorry for the length, and sorry I haven’t summarized all this in the CHIP yet. (PRs welcome!)
I’m trying to wrap up a different (post-quantum) project before taking some personal time.
(Note that the post-quantum project isn’t related to this change, and doesn’t need a lower base instruction cost. The primary benefactors of this change will be new developers and tooling maintainers, who won’t have to learn or develop workarounds in these edge cases.)
For now, I just pushed the one-sentence spec change here: https://github.com/bitjson/bch-loops/commit/9c1f55d9625e210c9c6eff113c3fa34049b586a5
Any comments or feedback appreciated, either here or in the repo. Thanks!