# How it Works

The Bitcoin Computer is a Javascript runtime environment that uses Bitcoin as a persistence layer.

# Storing Values

When an expression is evaluated with the Bitcoin Computer, the expression is inscribed into a Bitcoin transaction. If the value of the expression has object type, this object is considered a "smart object" and an output of the transaction is considered the object's id. If the value has multiple sub-objects, each sub-object is assigned a separate output as its id.

# Reading Values

To determine the value of a given smart object id, the Bitcoin Computer library will download the corresponding transaction and compute the value of the expression. As the mapping from sub-objects to outputs is deterministic and one-to-one, the software can determine which sub-object of the value is the smart object for the given id.

# Updating Values

In order to explain how updating values works we need the notions of "free variable", "environment", and "closure". Consider the Javascript expression:

const x = 1;
counter.add(x);

It contains two variables, x and counter. The variable x is defined in the expression and one can determine that the value of x is 1. The variable counter is not defined so it is impossible to tell what the value of counter is. Such variables are called free variables. In order to evaluate an expression with free variables, a definition of the values of the free variables is required. This is what an environment does: it maps free variables to values. A closure is a pair consisting of an expression and an environment.

To evaluate an expression e containing free variables x_1\ ...\ x_n with the Bitcoin Computer, the user needs to provide a Bitcoin environment \{ x_1: o_1\ ...\ x_n: o_n \} that maps the free variables of e to outputs o_1\ ...\ o_n. The Bitcoin Computer will recursively determine the values v_1\ ...\ v_n of the outputs o_1\ ...\ o_n respectively. It then creates a closure consisting of the expression e and the environment \{ x_1: v_1\ ...\ x_n: v_n \} and evaluates this closure with a standard Javascript runtime.

All sub-objects of the value returned are designated one output of the transaction. We refer to both the outputs as well as the values they represent as revisions. Note that when a closure is evaluated, the values v_1\ ...\ v_n can change (for example if e is a function call f(x_1\ ...\ x_n) with side effects). Therefore a these transactions must have outputs that represent the new revisions for these values as well.

The Bitcoin Computer protocol requires that a transaction spends all outputs in the environment. A practical advantage is that this provides a space efficient way to store the environment: Only a list of variable names needs to be stored as meta data and the full environment can be reconstructed from the inputs. It also has two important consequences: It provides a notion of data ownership as it is necessary to be able to spend an output in order to update it's value. And it makes it possible to run the Bitcoin Computer as a light client as the inputs of a transaction contain pointers to the transactions that contain the expressions that need to be evaluated first.

# Smart Contract Language

The programming language used for the Bitcoin Computer has the exact same syntax as Javascript. However there is one important semantic difference:

The class Contract is exported from the library. It enforces the following properties, which we think turn Javascript into a viable smart contract language.

# Assigning Properties Outside of Function Calls is Prohibited

Assigning to a property outside of a function call throws an error.

This makes it possible to write classes that impose constraints on all future values of an object. Consider for example the class Even below. The condition guarantees that all instances of the class will always have an even value.

class Even extends Contract {
  inc() {
    if (typeof this.n === 'undefined') this.n = 0
    else this.n = this.n + 2
  }
}

While this is not a very useful example for a constraint, all smart contracts are based on constraints to future values in a similar way.

# Keyword Properties Control the Transaction Being Built

The Contract class enforces certain types for the properties _id, _rev, _root, _amount, _owners, _readers, and _url:

type SmartObject = {
  readonly _id: string // output where object was created
  readonly _rev: string // output where object is currently stored
  readonly _root: string // useful for building fungible tokens
  _owners?: string[] // determines data ownership
  _amount?: number // determines number of Satoshis stored in the current output
  _readers?: string[] // determines whether object is encrypted and who can decrypt is so
  _url?: string // determines if data is stores off-chain
}

The properties _id, _rev, and _root are read only and set by the runtime to relay information about which transaction created the object and where it is currently stored.

  • The value of the _id property is the output (encoded as <transaction id>:<output index>) that represented the object immediately after it was created.
  • The value of the _rev property is the output of the currently representing the object (that is, the object's revision).
  • The value of the _root property is assigned once when the object is created and is never modified subsequently. If the expression that creates the object is of the form new C(...) then its root is equal to its id. If the expression is of the form x.f(...) then the root of the new object is equal to the id of x. Otherwise the root is set to n/a. The root property is useful for building fungible tokens.

The properties _amount, _owners, _readers, and _url can be set by the smart contract developer to influence how the transaction is built.

  • If a property _amount is set it needs to be set to a number. It determines the amount of Satoshi stored in the output representing the current revision. If it is not set the revision will have a minimal (non-dust) amount of Satoshi.
  • If a property _owners is set it needs to be set to an array of strings [p_1\ ...\ p_n]. These determine the output script of the current revision. Specifically, the script for the current revision is a 1-of-n multisig script with the public keys p_1\ ...\ p_n. This guarantees that only a user that has a private key corresponding to one of the public keys can update the object. If the property is not set it defaults to the public key of the computer that created the object.
  • If a property _readers is set it needs to be set to an array of strings [p_1\ ...\ p_n]. If this property is set the meta data in the corresponding transaction is encrypted such that only users with corresponding private keys can decrypt the expression and compute the value of the smart object. If the _readers property is not set the meta data is not encrypted and any user can compute the value of the smart object.
  • If a property _url is set it needs to be set to the url of a Bitcoin Computer node. If it is set the expression is not stored in the transaction but on the node instead. The transaction only contains a hash of the expression and the location where the expression can be obtained from the node. This is convenient if the expression is large, for example because it contains a lot of data.

# Assigning to this in Constructors is Prohibited

This is not a property that we think this will make Javascript a better smart contract language, it is just a consequence how we enforce the properties above. In order to have useful constructors it is possible to pass an initialization object into the constructor:

class A extends Contract {
  constructor() {
    super({ k1: v1, ... kn: vn })
  }
}

This has the same effect as setting assigning to this in a normal Javascript program

// not a smart contract, for illustration purposes only
class A {
  constructor() {
    this.k1 = v1
    ...
    this.kn = vn
  }
}