BitAuth IDE:  Write and Debug Custom Bitcoin Scripts

Bitauth IDE is a new open source project for designing advanced authentication schemes for bitcoin and bitcoin-like cryptocurrencies. It’s both a learning sandbox and a tool for designing new kinds of wallets.

An example showing the language, variable interpretation, inline evaluation, and some interactive debugging features. This example shows a two-key wallet (a 2-of-2 Vault) which includes a fallback to a Trusted Party. If either Signer 1 or Signer 2 is unable to sign a transaction, after a 30 day delay, the trusted party can help the remaining signer recover the funds. A line-by-line trace of the program state is visualized on the right half of the view.

Briefly: What is Bitcoin Script?

Bitcoin Script is the programming language used in bitcoin transactions.

It’s a stack-based language, and it’s used to describe the authentication requirements for some funds to be spent. This description is called a locking script, or more commonly a bitcoin address.

When you send money, you’re actually re-assigning the funds to whomever can authenticate for that address. Many users use a single key to hold their bitcoin, but it’s possible to create much more secure kinds of addresses.

For a detailed introduction to Bitcoin Script, and a basic walkthrough of Bitauth IDE, check out this video:

You can also read more about Bitcoin Script on the bitcoin.it Wiki. Below I describe in more detail the components of Bitauth IDE.

CashAssembly in 2 Minutes

CashAssembly is a very simple templating language for Bitcoin Script. If you have seen a disassembled bitcoin script, it may look familiar:

OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG

This is a disassembled view of a script (a P2PKH locking script) copied from the bitcoin.it Wiki. It’s in a common format used for describing script constructions. It’s actually valid CashAssembly:

In CashAssembly, this is interpreted as two operations (OP_DUP OP_HASH160), a Push of the variable pubkeyhash, and two final operations (OP_EQUALVERIFY OP_CHECKSIG).

CashAssembly makes the convention of surrounding data pushes with the characters < and > a core part of the language. This goes one step further:

This example (a P2SH locking script), shows the other core element of the language: an internal Evaluation. At compile time, the script inside of the $( and ) is first evaluated by the virtual machine, and the top stack item in the result is used in its place (like bash Command Substitution). This example results in the following valid P2SH script:

OP_HASH160 
OP_PUSHBYTES_20 0x70fa88150dd44dddc81bfc988bbb27b4aab5b23d OP_EQUAL

Funds sent to this script could be claimed by anyone able to produce a valid unlocking script; in this case, a Push of the UTF-8 encoded emoji: 🚀

Bitauth IDE continuously evaluates the script as you’re typing, always showing the entire execution of the program as written (an “omniscient debugger”). Stack values are displayed intelligently — if the binary data on the stack is recognized as a variable, the name of the variable is displayed. If it’s a valid Script Number, the number is displayed. You can hover over the item to see the full value in hex format. In this case, “f09f9a80" is the UTF-8 encoding for 🚀.

Looking Under the Hood

You’ll find some additional debugging information in your browser’s developer tools, including easy access to the bitcoin-ts library.

Click on any “stack line” in the evaluation viewer to see the underlying program state in the developer console.

Entities, Variables, and Templates

Projects in Bitauth IDE are called templates. A Bitauth Template includes all the information necessary to generate and manage a wallet using a given authentication scheme. The template defines the Entities involved in the wallet, as well as the data (Variables) for which each entity is responsible.

Here, when creating a shared wallet, Signer 1’s wallet must create a secret key called “first”; it must provide an estimate for the current time (~UTC time) called “block_time”; and it must request some input from the user, called “delay_seconds”. Signer 1 then provides their public key, and the other two values to Signer 2 and Trusted Party. Once the values have been shared, each entity is able to create addresses and sign transactions.

Templates also encode information about which virtual machines they support. For example, BCH_2018_11 is the identifier for the version of the Bitcoin Cash VM active on the BCH network since November 2018. BTC_2017_08 is the identifier for the VM active on the BTC network since August 2017 (SegWit).

While Bitauth IDE doesn’t yet support debugging in all virtual machines, it still allows you to mark templates with supported VMs.

Templates make designing and sharing new authentication schemes much easier. They can be exported and re-imported in JSON format.

A screenshot of the authentication template import/export view with part of the JSON template visible.

Towards Fully-Generalized Wallets

By encoding all of this information in a Bitauth template, it’s possible to create fully generalized wallet software—wallets capable of importing and using entirely new authentication schemes, without requiring software updates from the wallet developer.

This would allow for vastly more security and user-control in wallets. Whereas wallets today are primarily single-factor, any wallet which adds support for Bitauth templates can easily participate in complex multi-signature schemes.

Complex Treasury Management

For example, a company may choose to manage its treasury using a 4-of-5 multi-signature system (i.e. payments must be signed by 4 out of 5 trusted staff members). If 2 of these members leave the company or lose their keys at the same time, the funds become inaccessible.

To mitigate this risk, the company can designate a fallback which becomes active after a delay (e.g. after 30 days, a different group, such as the Board of Directors, is able to sign for the funds). Further fallbacks can be used to mitigate other risks to whatever extent the company requires.

This system is theoretically much more secure than any single-key system, because lots of users/devices must be simultaneously compromised to steal funds. However, if all of the users are using the same wallet, a malicious software update–and some bad timing–may still compromise the wallet.

For better security and a better user experience, what if each user could use a different wallet? If the scheme is defined as a Bitauth template, each user can simply import the template, and now their preferred wallet can support it.

Reduce Disruptions from Network Splits

Bitauth templates may also reduce disruption from network splits. For example, when an intentional network split occurs (e.g. a disagreement on protocol development), it can be very costly and slow for wallets to implement support for both sides.

What if wallet developers could update faster by modifying an internal Bitauth template, adding support without needing to modify their own key-management code? What if, instead of waiting for developers to add support, users could simply import a coin-splitting Bitauth template? More generalized wallets could help the ecosystem handle network splits with less disruption.

The Technical Summary

This project includes:

  • CashAssembly — a new low-level language capable of expressing anything in the assembly language of the targeted currency’s virtual machine.
  • CashAssembly compiler — a compiler which handles efficient data serialization and a powerful variable templating system with primitives like keys, times, and binary data. Variables are owned by Entities — a trust-center, like a single person or a device in a multi-factor wallet. All this information is encoded in a Bitauth template, a JSON file format for describing bitcoin authentication schemes.
  • Bitauth IDE — a web-based interface for developing Bitauth templates. It includes an editor with syntax highlighting, hover information, and autocomplete for CashAssembly. Beside each editor instance is a line-by-line visualization of the stack as evaluation reaches that line.
  • Modifiable opcodes — the underlying virtual machine implementations are composed of pure javascript functions which take the current program state and return a new program state. This makes them very easy to swap out, modify, and compose. This is helpful for testing new ideas and avoiding code duplication between BCH ↔ BTC ↔ BSV, for example.

The primary implementation is part of the bitcoin-ts project on GitHub. The web app is on GitHub at bitauth-ide. The language, compiler, and IDE are fairly-complete, but the VM implementations used in the interactive debugger still need a lot of work and testing. Contributions welcome!

Try it Out

You can try out the IDE at bitauth.com/ide. Please keep in mind this is alpha software, and you should always test on testnet before risking real money. Also, the IDE is not a secure place to store keys — do not copy private keys into the online version of the IDE. Instead (if you’re feeling brave), run the IDE offline by cloning the repo and running it yourself.

What’s Next

If you’re interested in contributing, please join us on GitHub at bitcoin-ts.

Particularly, we need help compiling VM implementations to WebAssembly so they can be run alongside the interactive versions (to check for accuracy). We’d love to work with contributors to Bitcoin ABC, Bitcoin Core, Bitcoin Unlimited, Bitcoin SV, and other implementations to get their VMs compiling to WASM.