Before introducing the off-chain computation, let’s first learn about the on-chain computation model adopted by almost all the existing smart contracts.
Figure 1 shows the on-chain execution model. The on-chain execution itself is deterministic: the transaction is executed by all nodes and they must agree on the final state.
Such requirements on state consistency unavoidably introduce limitations: it is slow and expensive. More importantly, operations like network requests are forbidden since they can result in different final states on different nodes (network requests may fail on some nodes and succeed on others).
The off-chain execution was first proposed to satisfy the need for
This model, unfortunately, also has limitations. The trust of off-chain workers is implied in this solution since the on-chain nodes can only know that these workers produce the results but not that they use the “right” off-chain input and do the execution faithfully. That’s why such a solution is usually only used by the chain development teams who host their own workers.
The key to the problem above is to find the “trusted” off-chain workers, and there are some candidates like verifiable computation methods like zero-knowledge proof, or hardware-based solutions like the secure enclave.
Phala is a trustless computing cloud whose miner nodes are all Secure Workers using secure enclaves. The secure enclave is usually implemented as a secure subsystem of modern processors and provides two important secure guarantees: confidentiality and execution integrity. This means that the malicious operators, even with physical access to the machines, cannot read the state in memory (since it is encrypted by dedicated chips), or manipulate the program execution to provide false results. With this, even the individual developers can rent their own off-chain workers from Phala blockchain and enjoy the benefits.
This drives us to design a new contract execution model, i.e., the Fat (PHAt) Contract, that is able to do off-chain computation. It is worth noting that we deliberately choose not to simply migrate EVM into a secure enclave since it was designed for on-chain execution and thus hard to extend.
The Fat Contract is meant to be written with Parity’s ink!. From the developers’ perspective, there is little difference when writing ink! contract and Fat Contract, except for the extensions we provide for Fat Contract. The key difference is where they are executed: the ink! contract is executed by Substrate nodes and Fat Contract in pRuntime (runtime customed by Phala) in our off-chain Secure Workers. Obviously, Fat Contract enjoys all the benefits mentioned above.
With Fat Contract, it’s now possible to implement the applications that used to require creating a new chain with a single contract.
The design principle for Fat Contract is simple: while supporting the legacy on-chain execution logic, it tries to provide a full-functional off-chain execution environment with privacy, high performance, and necessary features like Internet access and storage. Our insight here is that only a small portion of the state (like token balance and NFT ownership) in DApps really needs to be persisted on-chain, that’s why we encourage developers to implement most of their logic off-chain.
Talk is cheap and let me show you some code. This is the Hello World contract from ink!. As promised, you can run it in Phala with no modifications. In this contract, the contract (on-chain) state is described by variable value. And based on whether the state will be changed, the following functions are divided into two classes, mutable (flip() function) and immutable (get() function). Correspondingly, we divide the user’s requests to these functions into Commands, which are sent to mutable functions and change the on-chain state, and Query, which are sent to immutable functions and leave the on-chain state unchanged.
Among them, the Command follows the traditional off-chain execution path, except that it is encrypted and can only be decrypted in secure enclaves. This means Command, like normal transactions, needs to be posted on-chain, packed into the block, and then synced to off-chain workers for execution. It can be a performance bottleneck so should be used with caution.
Query, on the other hand, is very different. First, it is directly sent to the Secure Worker just like Client/Server communication, so it is free of the latency of blockchain transactions and the gas fee for execution (you rent the worker instead of paying for each instruction in Query processing). Second, Query is meant to change the local (off-chain) state. We further empower it with the ability to
In other words, when you are writing functions for Query, it’s more like you are writing a normal server program instead of a smart contract. But this time, your “server program” is executed on a real decentralized cloud, and can use the blockchain as the root of trust: each Fat Contract is allocated a key pair with the public key published on-chain. This key pair proves the program identity and can be used to sign any messages to prove that they are really produced by a certificated contract and thus can be trusted. This enables attestation operation, which is the basis of Oracle, Decentralized Identity, and other interesting Web3 applications.
Now, why not get your hands dirty and
Also Published Here