Programming Language: Preda

In the middle of 2023, I joined a Preda hackathon that kicked out on 18th November 2023.

I already have an interest in programming languages. So, I will use this hackathon to try out a new language. But what is Preda programming language?

The Language Specification

Official website: https://www.preda-lang.org/

Preda is a programming language used to increase transaction throughput for applications on blockchain platforms.

Preface

The applications in the blockchain platforms are called smartcontracts. Ethereum invented intelligent contracts, the first blockchain platform, in 2015.

Even in 2023, Ethereum is the most popular blockchain platform, setting the global trends in the cryptocurrency ecosystem. The Ethereum blockchain network has the Ethereum Virtual Machine (EVM), where smart contracts are executed. The platform provides various programming languages to write a smartcontract targeting EVM.

The most popular programming language is Solidity: https://soliditylang.org/.

However, EVM could process a single transaction simultaneously, which means a considerable delay during the high traffic.

There are many ways to solve the scalability issues. Most of the blockchain trend goes into building a blockchain of blockchains: Cosmos, Polkadot, Layer 2 blockchains, etc.

Preda is taking an unusual direction to increase scalability by creating distributed intelligent contracts.

Distributed Smartcontracts

 To understand a distributed smartcontract, think about a popular web application. Imagine a web application that serves thousands of requests at a time. How would you scale the server to serve multiple requests?

The intuitive way to execute multiple requests simultaneously is by creating multiple copies of the application (as a cluster) that run the requests in parallel. But there is a better approach. You could split the app into smaller inter-connected parts rather than creating a copy of the same code. Then, create a cluster of the parts that have a heavy load. When an app consists of multiple inter-connected parts running in parallel, this app is called a distributed application.

Almost all modern web applications are distributed with at least a client, server, and database.

Similarly, a distributed smart contract consists of multiple parts that execute the transactions together.

As I mentioned in the Preface, the current EVM supports a single transaction simultaneously. So, Solidity is created for a single transaction as well.

To create distributed intelligent contracts, we need a blockchain that supports distributed systems and a programming language to execute and make asynchronous calls between various allocated parts.

Even in modern EVM, you can split an app into multiple intelligent contracts. But their interaction is synchronous, so it blocks all requests until other smart contracts won't complete the execution.

Contract A could send request A to contract B by making the requests asynchronous. Meanwhile, execute the request B from the transaction pools.

Preda is the programming language used to make asynchronous calls between smart contracts, which solves the second problem for scalable execution.

From dioxide.network

But why was Preda invented?

This is a Smartcontract.

Motivation behind Preda

As in most aspects of social interactions, the top 1% of the services get the majority of the traffic. So, scalability is needed for them.

Source: https://www.theblock.co/data/on-chain-metrics/ethereum/top-20-gas-consuming-smart-contracts-30d

Just look at Uniswap, which has about the 18th transactions, while Scroll has 2 thousand transactions. All other two million transactions deployed on Ethereum get less than 2000 transactions.

Notes on specification

Preda is a new programming language that extends Solidity by adding asynchronous calls between intelligent contracts.

To support such kinds of smart contracts, the Preda team also created a blockchain network for that: https://dioxide.network/

The Preda programming language specification Old: https://www.preda-lang.org/pdf/preda-model-sole.pdf

The Preda programming language specification: https://preda-lang.org/pdf/PREDA_Model_as_an_Experimental_New_Smart_Contract_Language.pdf

Here are the notes I took by highlighting the critical parts of Preda.

Preda stands for Parallel Relay Execution Distributed Architecture. Preda introduces two models:

  • Programmable Scope: an isolated state of the smartcontract. Define the scope by data access pattern, which narrows and minimizes the data dependency between the states.
  • Asynchronous Function Relay: a transaction logic that moves execution from one programmable scope to another. The function relay is defined with the explicit data dependency.

In Solidity on Ethereum, the smartcontracts are defined as a set of variables (state) and functions (transaction functions). The state and functions are described in the global scope. However, it presents two significant challenges in scaling intelligent contracts.

1. Partitioning the state requires understanding the data access patterns associated with the state variables. The Preda solves it by introducing a Programmable Contract Scope (κ-scope).

2. A function defined on a global scope requires the availability of all functions and state variables. The Asynchronous Functional Relay (λ-relay) narrows the scope for a function to execute. The λ-relay decomposes the execution of k-scopes in the order of data dependency.

In Preda, when invoking a function, it must provide a target k-scope, an analogy 'this' pointer in C++.

Special k-Scopes

Engine Scopes = φθ(i): one instance of k-scope built in for each instance of the execution engine to represent a scope available for immediate read/write by any function executing the current execution engine. The engine scope is not allowed to be the target of λ-relay nor be referred to by specifying θ(i). The variables and functions in the engine scope can be accessed only by the i-th engine.

Global Scopes =  φΩ: a built-in k-scope that logically singletones the entire network.

PREDA model strictly prohibits referring to a specific instance of an execution engine or making assumptions on the underlying configuration (for example, the number of execution engines).

In PREDA, the scopes are defined by fine-grained boundaries of contract states. The actual partitioning strategy is left to the hosting execution engine.

Relaying

A function initiating a transaction must trigger a λ-relay to execute on another k-scope. The λ-relay is converted into a relay transaction by the host. The relay transaction will be passed to the memory pool as an unordered pending transaction in the destination engine.

Global scope transactions will be executed first before conducting an engine scope.

Cross-contract invocation can be carried out immediately without doing a relay transaction.

Syntax

State variable defined and instantiated in a k-scope as:

var_type @scope var_name;

The @scope specifies a k-scope. It can be:

  • @global, which is by default, thus can be omitted.
  • @engine, for engine scopes.
  • @address or @uint: a keyed k-scope based on the Solidity elementary type name.

Functions in the k-scope are always defined as:

function fun_name(arg_type arg,..)
        @scope modifiers returns (ret_type) {}

The @scope values are identical to the variable definition.

In the destination k-scope, the target scope and global variables are merged and available as read-only variables. Symbols defined in the current engine are available for read and write.

relay @key (var1, var2, ...) {}
 relay @global (var1, var2, ..) {}

The above code defines a relay transaction to continue the execution in another scope. The relaydefines a lambda function that is executed in the destination scope.

// scope a
 relay func_name_k(var1, var2);
 // scope b
 function func_name_k(var1, var2) @scope public {}

Besides passing a lambda function, Preda can also call a named function as defined above. The named functions must be public.

The named transaction could be a cross-contract call as well as:

relay @key ExtContr(a_addr).named_func_k(var1, var2);
 relay ExtContr(a_addr).named_func_k(var1, var2);

Here, the @key is defining the scope of the ExtContr.

The mappings are defined as:

mapping<type => type> @scope var_name;

Note that any current Solidity smartcontract can be compiled into Preda as is. In this case, all variables and functions will be in the global scope. The global scope is not scalable; therefore, the design goal of the developers is to minimize the global scope.

Potential Execution Engine

  • Multi-core single node.
  • Sharded node
  • Multiple Single Nodes across the internet

The guideline on how to use Preda is described on Preda Guideline.