Pure Attributes or Implementing Functional Smart Contracts From The Scratch at Home
TLDR: A simple data model that helps if you are trying to implement a new smart contracts machinery from the scratch at home. With JavaScript and functional programming.
Avoiding side effects
Smart contracts are crucial pieces of code, which should be simple to write and test.
While serious development is going on these days in the area of formal code verification, the Pure Attributes idea is about using existing and widely accepted in industry approaches of functional programming.
What if a smart contract would be possible to represent as a function with no side effects so that it is easy to test and to reason about? How could it work?
Let’s do some prototyping and create a function which could act as a very simplified smart contract code for some imaginary cryptocurrency token.
Our function will receive 3 arguments:
- orig the origin account address
- dest the destination account address
- value the number of tokens to transfer from origin to destination
The getAttribute and updateAttribute are system built-in functions, responsible for retrieving and updating user information, associated with this smart contract. We are particularly interested in updateAttribute, which represents side effect taking place in our transfer function.
How can we get rid of it, so that there are no changes to the system state inside the function body? Let’s try to write a new version of this code.
What have we done here and what does it mean:
{
target: dest,
name: 'balance',
value: destBalance + value
}
We have got our function executed and returned the results of calculations, which says: Set attribute with name balance of target address dest to new value destBalance + value.
The underlying code will take it, check the returned values and save results of the calculation.
Code contracts
Noticed that in the second example there is no boundaries check for the returned balances?
Now we can omit these checks from the main code logic in order to make it cleaner and delegate all the validation to the special functions.
function validateBalance(balance) {
return balance >= 0 && balance <= MAX_BALANCE;
}
The returned list of attributes will be automatically verified with these predefined functions and if valid, account’s attribute balance will be updated accordingly to returned values.
Using functional language
What’s the point of it? With the very first code example, it would also work just fine, right?
Using side-effect free functions open doors to using a real functional language, which brings additional benefits to our code — the absence of null and data structures immutability.
Let’s rewrite this small example in Elm.
Unlike hand-written JavaScript, Elm code does not produce runtime exceptions in practice. Instead, Elm uses type inference to detect problems during compilation.
http://elm-lang.org/
This can drastically improve code testability and verification. Elm is used here as an example. It is also possible to use other compiling to JavaScript languages like PureScript, TypeScript, Clojure.
Attribute coordinates
We have now 2 coordinates which allow us to identify attributes of an address — account address, attribute name.
So far so good. But what if we want to create several smart contracts? How would we know what function to call?
It looks like we need another coordinate, an identifier for a smart contract. Let’s call it self.
Would it be handy to have a possibility to call not only the default function of our smart contract transfer but also introduce other functions? How would we address them? Using another attribute coordinate — key, which represents the function name.
Now, let’s create a transaction on our new blockchain which transfers some number of tokens from address orig to dest.
{
"orig": "origin address",
"dest": "destination address",
"value": 100,
"self": "smart contract address",
"key": "transfer"
}
Or, a transaction which creates a new smart contract:
{
"orig": "origin address",
"dest": "self — destination address",
"value": "smart contract code"
}
Now we have a simple mental model, allowing us to easily implement a smart contracts engine using side-effect free functional programming approaches.
More code examples and working prototype can be found on https://github.com/slavasn/bloqly