FATE: Revolutionizing Smart Contract Execution
Enhancing Efficiency and Safety in Blockchain Applications
Posted: 2023-05-31Introduction
Smart contracts serve as the building blocks for decentralized applications. At HappiHacking, we had the privilege of collaborating with æternity, a blockchain platform built on the BEAM in Erlang. Together, we embarked on a mission to develop a virtual machine that would revolutionize smart contract execution. This blog post takes you through our journey and highlights the key features of FATE (Fast æternity Transaction Engine), an innovative solution that enhances efficiency and safety in blockchain applications.
The Genesis of FATE
HH (HappiHacking) was approached by æternity who were building a blockchain on the BEAM in Erlang. They wanted to have a virtual machine to execute smart contracts on their new blockchain.
We were invited to a meetup with the development team in Sophia, Bulgaria two weeks later. Neither I nor Tobias new anything about blockchains at the time. So I sat down with the Ethereum "yellow paper" (sic!) to learn something about the technology. In order to really understand the Ethereum virtual machine, the EVM, I implemented a version of it in Erlang. I called this VM "AEVM" for the æternity Ethereum Virtual Machine.
Me and Tobias were very excited to go to Sophia and learn everything about blockchain from the development team. After a few intensive days of discussions we realized that the blockchain technology was in its infancy and very new, no one new that much about the technology, how to implement it or even which features to implement.
When I showed the team my AEVM implementation, everyone was impressed and we got a very central position in the æternity core team.
Taking the Lead in Technical Decisions
For the next two years me and Tobias lead many of the technical decisions and coded much of the core of æternity. When the main features of the blockchain were implemented we started thinking about how to really design a virtual machine for the blockchain.
Identifying the Vision for Smart Contracts
We identified a number of properties we saw or wanted to see in Smart Contracts:
- Short run time
- Deterministic
- Reusable
- Easy to understand and verify
- Easy access to æternity specific features (Oracles, Contracts, Channels)
Challenges with Existing Solutions
We also saw a number of problems with the design of Solidity, the Ethereum smart contract language, and the design EVM which also affected the AEVM. The EVM was modeled after a computer. It had stack slots, and memory addresses, word length, and arithmetic that could overflow or silently fail.
The Solution -- Sophia and FATE
To address these challenges and create a superior smart contract execution environment, we developed the Sophia programming language. Sophia embodies the following principles:
- Static Typing: Sophia is statically typed, ensuring type safety and reducing common programming errors.
- Concurrency Control: While allowing parallelism, Sophia avoids true concurrency, simplifying execution and enhancing safety.
- Well-Defined Errors: Sophia incorporates comprehensive error handling mechanisms, providing clear and unambiguous error messages to developers.
- Safety Focus: With Sophia, safety is prioritized through design choices that prevent vulnerabilities and protect against attacks.
- Blockchain Integration: Sophia is closely integrated with the æternity blockchain, offering seamless access to its unique features.
- Data Structure Efficiency: Sophia emphasizes well-defined serialization and storage mechanisms, eliminating unnecessary complexities.
We also designed a type-safe high-level virtual machine for smart contracts. FATE is highly optimized for Sophia and the æternity blockchain. FATE is the culmination of our efforts, embodying the principles outlined above.
No Memory Limit
Fate removes the traditional memory limit found in other virtual machines. Instead, it introduces gas control to manage the execution of smart contracts. Gas acts as a resource limit and ensures that computations within smart contracts do not exceed the available resources. By removing the memory limit, Fate offers more flexibility in executing complex computations without being restricted by memory constraints.
Gas Controlled
Gas control is a fundamental aspect of the Fate virtual machine. Each operation and computation within a smart contract consumes a specific amount of gas. The gas consumption determines the cost of executing the contract. Gas control ensures that smart contracts are executed within the specified resource limits and prevents malicious or computationally expensive code from monopolizing the system. By incorporating gas control, Fate promotes fair resource allocation and efficient contract execution.
No Concurrency (Parallelism Possible)
Fate operates without native support for concurrency. While individual contracts run sequentially, the absence of concurrency within a single contract enhances determinism and simplifies contract development, testing, and debugging. External parallelism could be achieved by executing multiple contracts or transactions concurrently, leveraging the inherent scalability of the underlying blockchain network.
Statically Typed (No Floats)
Fate employs static typing, which provides enhanced safety and predictability in smart contract development. Static typing requires variables and data types to be explicitly declared and verified at compile-time. This approach eliminates common type-related errors and improves code correctness. Additionally, Fate avoids the use of floating-point numbers, which can introduce complexities and potential precision issues. By adhering to a statically typed model and excluding floats, Fate enhances contract reliability and predictability.
Well Defined Errors
Fate ensures well-defined errors during contract execution. This feature helps developers identify and handle exceptions, errors, and invalid operations within their contracts. Clear error messages and exception handling mechanisms enable efficient debugging and troubleshooting, facilitating the development process and enhancing contract robustness.
Close Integration to Blockchain
Fate is designed for close integration with the blockchain it operates on, such as the æternity blockchain. This integration allows seamless interaction between smart contracts and the underlying blockchain infrastructure. Fate leverages æternity-specific features, such as oracles, contracts, and channels, to enable efficient and secure communication, data exchange, and execution of blockchain-based applications.
Stack-Based
Fate follows a stack-based execution model, where operations are performed on a stack of data elements. This model simplifies the execution process and enables efficient memory management. The stack-based approach allows for compact bytecode representation and optimized execution, making Fate well-suited for resource-constrained environments like blockchain networks.
Well Defined Serialization
Serialization refers to the process of converting data structures or objects into a format suitable for storage or transmission. Fate ensures well-defined serialization mechanisms, which enable efficient and reliable serialization of data within smart contracts. This feature is crucial for a blockchain which depends on determinism.
By incorporating these features, Fate provides a powerful and efficient execution environment for smart contracts. Its gas control, stack-based execution, well-defined errors, and close integration with the blockchain contribute to the secure and reliable execution of contracts on the æternity blockchain. Developers can leverage Fate's features to build sophisticated, deterministic, and high-performing applications on the blockchain.
Fate has the following built in types, in the virtual machine language.
-- Fate types
Integer -- signed arbitrary precision integers
Boolean -- (true | false)
Address -- A pointer into the state tree
Contract | Oracle | Oracle_query | Channel
String -- utf8 encoded byte arrays
Bytes
Tuple (), ('a), ('a, 'b, ...)
List -- Cons cells (‘a) | Nil (Ʇ)
Map (‘a, ‘b) -- (Key: ‘a -> Value: ‘b) ‘a not a map
Variant (| [Sizes] | Tag | Elements |)
Bits
TypeRep
In a blockchain virtual machine, such as FATE, the design choices regarding code structure, code addresses, and data size play a crucial role in ensuring the integrity, security, and efficiency of smart contract execution within the blockchain ecosystem. We decided to have no memory addresses in FATE to make it impossible to trick the VM to execute the wrong code. Instead we have the following design:
-
Basic Blocks (BB): The code structure is organized into Basic Blocks. A Basic Block is a sequence of instructions that can be executed without interruption. By dividing the code into Basic Blocks, the VM can optimize the execution process, handle control flow efficiently, and provide better security and auditing capabilities.
-
Absence of code/instruction addresses: In FATE, there are no specific addresses assigned to code instructions. This is primarily done to enhance security and prevent arbitrary code jumps or modifications. By removing direct access to code memory addresses, the VM ensures that the execution of smart contracts follows a predefined and controlled path, reducing the risk of malicious or unauthorized code manipulation.
-
Function-centric code organization: Each function within a smart contract has its own code. This separation allows for modularity and encapsulation of functionality. It enables efficient code reuse, improves readability, and simplifies the debugging and maintenance processes. Moreover, by isolating functions, the VM can manage resources and handle function calls in a structured and controlled manner.
-
Unspecified data size: FATE does not impose a predetermined size for data. This flexibility is essential to accommodate varying data requirements of different smart contracts. It allows for the storage and manipulation of data structures of different sizes, ranging from small integers to large arrays or complex objects. By not limiting the data size, the VM promotes versatility and adaptability in smart contract development. It also removes all possible overflow bugs and attacks.
-
No defined word size: Unlike traditional computer architectures, FATE does not enforce a fixed word size for instructions or data. This design choice grants flexibility to the VM implementation, allowing it to optimize memory usage and adapt to the specific requirements of the blockchain platform. It enables efficient storage and processing of data without unnecessary overhead or constraints imposed by fixed word sizes. This also removes all possible overflow bugs and attacks.
-
Flexible data storage: The implementation of FATE has the freedom to choose how data is stored. This flexibility ensures that the VM can utilize the most suitable data structures and storage mechanisms for the given platform. It enables efficient data retrieval, manipulation, and persistence while considering factors such as storage cost, access speed, and compatibility with the underlying infrastructure.
-
Absence of word size or byte size addresses to memory: In FATE, memory addresses are not defined based on word size or byte size. This design decision allows for a more abstract and agnostic representation of memory, decoupling it from specific hardware architectures. It enables the VM to handle memory operations in a platform-independent manner, promoting compatibility and portability.
Overall, these design choices aim to strike a balance between security, efficiency, flexibility, and compatibility. By carefully considering the unique requirements and constraints of blockchain systems, the VM can provide a reliable and robust execution environment for smart contracts, fostering trust, transparency, and decentralized application development.
Let us look at some code examples. Here is a simple Solidity (the default language of Ethereum and EVM) contract with just an identity function.
Solidity
// Solidity
pragma solidity ^0.5.11;
contract Identity {
function id(int256 X) public pure returns (int256) {
return X;
}
}
Here is the same contract in Sophia.
Sophia
// Sophia
contract Identity = payable entrypoint main (x:int) = x
Note how much shorter just such a simple contract is and also that in Solidity you have to specify the word size of your integer.
If we compile the Solidity Identity to the Ethereum Virtual Machine (EVM) assembly language we get a quite large program:
PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO
PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP
PUSH1 0xAB DUP1 PUSH2 0x1E PUSH1 0x0 CODECOPY PUSH1 0x0
RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE
DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT
JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x28
JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1
PUSH4 0x1A94D83E EQ PUSH1 0x2D JUMPI JUMPDEST
PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x56 PUSH1 0x4
DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO
PUSH1 0x41 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2
ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD
SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x6C JUMP
JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE
PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1
SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP2 SWAP1
POP SWAP2 SWAP1 POP JUMP INVALID LOG2 PUSH6
0x627A7A723158 KECCAK256 0xc2 0xb9 0xdf 0xb0 0xc8
0xdf 0xf6 SWAP14 SWAP14 0xe9 0x46 0xcd PUSH17
0x1D21108C0786A26266D0F114ADBF024CDE 0x4b 0xd1
PUSH5 0x736F6C6343 STOP SDIV SIGNEXTEND STOP ORIGIN
If we compile the Sophia Identity contract to AEVM we get a slightly smaller bytecode:
PUSH3 0, 0, 100 PUSH3 0, 0, 132 SWAP2 DUP1 DUP1 DUP1
MLOAD PUSH32 185, 201, 86, 242, 139, 49, 73, 169, 245,
152, 122, 165, 5, 243, 218, 27, 34, 9, 204, 87, 57, 35,
64, 6, 43, 182, 193, 189, 159, 159, 153, 234 EQ PUSH3 0,
0, 192 JUMPI POP DUP1 MLOAD PUSH32 104, 242, 103, 99,
56, 255, 80, 136, 57, 171, 164, 119, 73, 239, 250, 139,
232, 126, 242, 132, 242, 7, 251, 61, 153, 152, 112, 28,
213, 56, 135, 197 EQ PUSH3 0, 0, 175 JUMPI POP PUSH1 1
NOT MLOAD STOP JUMPDEST PUSH1 0 NOT MSIZE PUSH1 32 ADD
SWAP1 DUP2 MSTORE PUSH1 32 SWAP1 SUB PUSH1 3 DUP2 MSTORE
SWAP1 MSIZE PUSH1 0 MLOAD MSIZE MSTORE PUSH1 0 MSTORE
PUSH1 0 RETURN JUMPDEST PUSH1 0 DUP1 MSTORE PUSH1 0
RETURN JUMPDEST MSIZE MSIZE PUSH1 32 ADD SWAP1 DUP2
MSTORE PUSH1 32 SWAP1 SUB PUSH1 0 NOT MSIZE PUSH1 32 ADD
SWAP1 DUP2 MSTORE PUSH1 32 SWAP1 SUB PUSH1 3 DUP2 MSTORE
DUP2 MSTORE SWAP1 JUMP JUMPDEST PUSH1 32 ADD MLOAD MLOAD
MSIZE POP DUP1 SWAP2 POP POP DUP1 SWAP1 POP SWAP1 JUMP
JUMPDEST POP POP DUP3 SWAP2 POP POP PUSH3 0, 0, 140 JUMP
When we compile the Sophia Identity contract to FATE we get:
FUNCTION init() : {tuple,[]}
;; BB : 0
STORE store1 ()
RETURNR ()
FUNCTION main(integer) : integer
;; BB : 0
RETURNR arg0
That's it. That is the actual FATE assembler code. Short, readable and to the point.
In conclusion, the FATE (Fast æternity Transaction Engine) virtual machine offers several advantages in terms of safety, efficiency, and cost-effectiveness compared to other blockchain virtual machines like AEVM (æternity Ethereum Virtual Machine).
Overall, FATE serves as an efficient and secure transaction engine for executing smart contracts. Its type safety, deterministic nature, gas-limited memory, and execution provide a reliable and predictable environment for building decentralized applications. With its compact bytecode and improved performance, FATE offers an enhanced user experience and cost-effective utilization of blockchain resources.
Conclusion
In the æternity project we used many of the services that HappiHacking is known for:
- Rapid Prototyping
- We developed the AEVM in two weeks, proving that it would be feasible to write a virtual machine for æternity.
- The Happy Path Method
- Through the project we developed the most important aspects first and quickly without sacrificing quality and performance. Steering the project forward with a gentle hand even when we didn't have formal leadership roles.
- Rubberducking as a Service
- We were there for the rest of the development team and management to discuss ideas and solutions.
- Erlang & Beam Expertise
- With our long experience in developing production quality Erlang systems we managed to get a performant, reliant, robust and scalable blockchain system built in time.
- Full-Service Project Partner
- We took an ide that was mostly in the head of the founder of æternity and turned it into a design, architecture, a working system, and a live deployment.
- Deep-dive analysis and problem solving
- We took our time to really understand the domain, and then we designed Sophia and FATE. We also worked on many other problems in the blockchain world such as Merkle Patricia Tries, oracles, state channels, names, accounts, Bitcoin.NG, proof of work and more.
- System Validation through Tech Lead Mentoring
- Me and Tobias embedded ourselves in the development team and could mentor more junior developers, review code and make sure the system architecture was solid.
- Team management
- Happi often lead daily stand ups and discussion when the team met.
- Project management
- We helped the formal project manager with the direction of the project on a higher level.
We will try to come back with another blog article about some of the lessons we learned implementing a block chain from scratch. (Hint: Patricia Merkle Tries are really cool).
We were not alone in the project so I want to give a big thank you and shout out to the whole team, you know who you are!
Happi Hacking AB
KIVRA: 556912-2707
106 31 Stockholm