I’m a bitcoin person, but I’ve been paying more and more attention to Ethereum over the past few weeks. I have some Ether, but I’m still probably an outsider looking in when it comes to Ethereum.

I’ll start by saying I like aspects of Ethereum. I think they’ve improved upon certain things bitcoin was having trouble with. And while it has its downsides, the one that I speak most positively about is the fact that they’ve done away with UTXOs. Instead, they maintain account balances while dynamic behavior is moved into contracts. I’ve personally had a hell of a time trying to optimize the utxo set in my own bitcoin full node. It can be a real pain (bitcoin currently has 38 million utxos in 10 million different unspent transactions).

But while some of the features of Ethereum seemed attractive and inviting, there was one major component of Ethereum that always rubbed me the wrong way: how dynamic the contract language is. It’s a far cry from bitcoin’s scripting system.

Bitcoin Script History

Before we get into all that, some relevant info on the way I see things:

I’ve spent the past 7 months syncing the bitcoin blockchain repeatedly to test my full node. I’ve maybe used more of sipa’s bandwidth than anyone (sorry, sipa, your node is usually the fastest). I’ve seen bitcoin history replay in my terminal hundreds of times.

So it follows that I’ve also seen a lot of weird scripts. For example, I can tell you when the first p2sh script appeared on the blockchain. The weird part is, this script wasn’t executed as p2sh yet because p2sh only went into effect 23 days later.

I can tell you when OP_CODESEPARATOR first appeared on the blockchain, along with other non-push opcodes in the input script. The output script even has a OP_NOP2 OP_DROP: the same convention we now use for OP_CHECKLOCKTIMEVERIFY, and this was ages before CLTV. I regard that one as the coolest TX ever sent.

I can tell you when the SIGHASH_SINGLE bug was first used in tandem with FindAndDelete() on the testnet blockchain. That was first time valid signatures ever appeared in a scriptPubkey! It was long thought to be logically impossible (and it is, but sighash_single allows a way around that).

And finally, I can tell you that the reason I discovered all of these is because my scripting system was originally failing to execute them properly.

Because of this, I absolutely concede that the bitcoin scripting system has really really weird parts that are more dynamic than you’d expect. But still, it’s a pretty primitive little language. It’s pretty hard to write a script with holes in it as long as you understand how a stack works. And it is still in stark contrast to Ethereum’s contract language.

(Now, you might be expecting me to go into detail about which has prettier syntax. Unfortunately, that’s already been done by a similarly named blog post.)

The bitcoin scripting language is comprised of 116 opcodes (not including the 1–75 push opcodes). Most of these are not allowed to be used in any standard script type, and some are disabled completely. The 15 disabled opcodes opened up attack vectors that could be used to DOS the network with a single script, and this was a certainty (this included shifts, multiplication, division, and string manipulation). On the other hand, the opcodes not allowed in any standard script types were just considered “too weird” to be in output scripts, and they weren’t generally used anyway. Perhaps they opened up room for people to write less-than-foolproof scripts, but who knows? Most nodes won’t relay transactions containing non-standard script types, but they are allowed on the consensus layer still (the blockchain).

It wasn’t until late 2014 that the scripting language was opened up again: p2sh redeem scripts are now allowed to be non-standard scripts, with a catch: p2sh does not and has never allowed non-push opcodes in the input script, even on the blockchain.

So, all of this development fuss of disabling opcodes, considering only a few script types standard, and re-enabling non-standard scripts was over a primitive little scripting language that doesn’t have half the features of Ethereum.

The DAO

A few days before the DAO got drained, I shared some of these thoughts about the scripting system with @mckie. I kept thinking that Ethereum was going to run into the same issues as the bitcoin scripting system: too dynamic, too many unknowns, too many ways to break. Except in the case of Ethereum, these problems would be amplified by the fact that it is more dynamic than bitcoin script ever was.

People are comparing the DAO incident to Satoshi’s int64 overflow bug back in 2010. I don’t think it is a logical comparison for a few reasons:

No funds were stolen there. Satoshi didn’t blacklist an address or artificially reclaim funds. This was a bug involving an int64 overflow that Satoshi would have fixed anyway, hacker or no hacker. Satoshi didn’t tell exchanges to stop trading and single-handedly control the market. This was in 2010. There was a lot less at stake back then.

And finally, Satoshi did not rewrite history. He fixed a bug. Bitcoin users, including miners, upgraded and began to reject the blocks exploiting the bug. The bad chain was eventually reorg’d and overtaken by the new main chain.

There’s a much more obvious comparison to be made here…