Praxis Programming Model and VM

Incentum
4 min readMay 14, 2019

--

Praxis uses a simple, elegant, and powerful programming model. All objects in Praxis are represented as JSON documents, and the JSONata query and transformation language is used for data transformations. First, some terms:

  1. Ledgers are key pairs and represent accounts.
  2. Templates are a set of Reducers, which are named bits of JSONata code that execute the contract logic.
  3. Coins are abstract and general, and can represent any asset. Coins are ‘minted’ by Contracts, and have a symbol, a globally unique mint identifier, an amount, and decimals.
  4. Contracts are running instances of Templates.
  5. The State is a JSON object containing the current state of the Contract, and the current Coins available in the Contract.
  6. The available Coins and data in a Ledger that are available for consumption are represented as Outputs. Basically, Outputs are the generalized equivalent of Bitcoin UTXO’s.
  7. Minted Outputs are new Coins minted by the Contract.
  8. Inputs are signed Outputs.
  9. Actions are Inputs, arbitrary JSON data, and a Reducer name.

Key Concepts

There are a few key concepts to understand in order to write contracts with Praxis effectively.

Contract Execution

A Contract is started by instantiating a Template, usually be running the start Reducer on a Template. Actions are then sent to the Contract to execute the contract logic. When an Action is executed, the Reducer is passed the Action, the Inputs, arbitrary JSON data, the current State, and the current Coins in the Contract. It produces zero or more Outputs, zero or more Minted Outputs, and a new State.

This leads to a very modular programming style, and makes the contract logic very understandable.

If an Action fails, the Inputs are not consumed and the Outputs will be available in their original Ledgers.

Using Outputs

A very important concept in Praxis is how to use Outputs correctly. Outputs in a Ledger are anything that is available for consumption. In other words, they can be signed by the Ledger and used as Inputs to Actions on contracts. An Output usually contains Coins, but this is not required. This is a key point. Outputs are used as the communication mechanism for Contract developers. If your Contract logic requires some signed data or Coins from a Ledger in order to execute a future action, then create an Output on that Ledger asking for the appropriate data. Each Ledger can easily see its list of available Outputs, so the Ledger can act on any that need processing.

Coins

Each Output and the Contract State can contain any number of different Coins. As stated above, Coins are an abstract representation of any asset. They can be used as normal Coins, or to tokenize any asset. Once something is converted to a Praxis Coin, it can be used in a Contract.

Coins are ‘minted’ by Contracts. One of the possible outputs from an Action are called Minted Coins. These are just like normal Coins, but they have their origin and identity derived from the Contract. The Contract address is used as the globally unique identifier for the Coin, and the minted Coins are turned into Outputs.

Coins are input and output from Contracts. The Contract checks that the input amount for each Coin is greater than or equal to the Outputs for the life of the Contract. If this invariant is not satisfied, the Action will fail. The Contract writer is responsible for handling each Coin input into a Contract Action. Either it must be captured by the Contract, or added to an Output.

VM Considerations

Our production VM will include one (or more) of the following options, and will satisfy the requirements of a blockchain VM as described here. And of course all components of Praxis, including the VM, will be fully audited by us, the community, and security and other experts.

  1. JSONata is a small, functional, interpreted language. We have full control over the interpreter. Currently, Smart Contracts run in a sandbox using vm2(on Node.js).
  2. We have started a sub-project to get the JSONata interpreter running in WebAssembly. We are porting the JSONata interpreter to AssemblyScript (TypeScript) which compiles to WebAssembly. We can also leverage the great work Parity has done with wasmi if needed. Although not 100% complete at the this time, it is highly likely this will be used in production.
  3. Support WebAssembly as a Reducer language. Other languages or paradigms can be used to execute Praxis Smart Contracts, without altering the programming model. A Reducer is just a blob with a language identifier attached to it. So when we support WebAssembly as a Reducer language (a fairly easy task), then any language that compiles to WebAssembly can be used. We will most certainly be adding this in the near future.

--

--