The idea of the records nano-kernel is Core to ZEXE, and enables a new cryptographic primitive called decentralized private computation (DPC). DPC is an application-ready framework that any developer can use to build custom applications. Transactions in the DPC scheme are executed in compliance with the RNK. These are decentralized by definition, since the RNK gives users control in determining the conditions under which their assets can be consumed through custom birth/death predicates.
The Record Nano-Kernel
Continuing to unravel ZEXE’s design, the next design-step was to strike a balance between the two aforementioned extremes in design. That is, supporting arbitrary functions, and using tags to identify functions.
Recall that the aim with ZEXE is to have concurrent processes share a ledger without violating the integrity or confidentiality of one another. An operating system of sorts is therefore needed to manage user-defined functions. Such management entails
- providing process isolation
- determining data ownership
- handling inter-process communication.
ZEXE’s authors decided to formulate a minimalist shared execution environment that imposes simple, yet expressive, rules on how records may interact. That is, a “nano-kernel” that manages records, and hence called the Records Nano-Kernel (RNK). The RNK enables the management of records by allowing users to define special functions that inspect legitimacy and validity of records being consumed or created. So, records can only participate in transactions if they satisfy these functions.
Consequently, a record carries more information than usual. It contains a data payload, together with two user-defined functions called predicates, a birth predicate which is executed when r is created, and a death predicate which is executed when r is consumed.
By suitably programming these two predicates, a user fully dictates the conditions under which a record r is created or consumed. Predicates of all records that are involved in a transaction are given the transaction’s local data, as a common input. The transaction’s local data contains; every record’s contents, a transaction memorandum (i.e., the publicly revealed piece of shared memory), an auxiliary input (i.e., the memory piece kept hidden), and any other construction-specific data.
So, each predicate can independently check if the local data is valid according to its own logic. That way a record can protect against other records that may contain ‘bad’ birth or death predicates, since those should evaluate to ‘False’ given local data intended for another function.
As before, zero-knowledge proofs guarantee that both the death predicates of consumed records and birth predicates of created records are satisfied.
Predicate Examples under the RNK
The next examples illustrate how the RNK can be used to design applications, such as custom assets and conditional exchanges.
Example 1: Custom “Tokens” or Digital Assets
Consider the use case of custom digital assets. In this case, we want to create assets and subsequently conserve them. So we can use records with payloads that encode assets identifiers id, the initial asset supply v, and a value v. That is, payload=(id,v,v=v).
We fix the birth predicate in all such records to be a mint-or-conserve function, MoC. This means MoCis responsible for creating a new supply of a new asset and subsequently conserving the value. A record with the asset identifier id is either creating the initial supply of a new asset (“mint”) OR ensuring the total supply of the asset in circulation does not increase during a transfer between parties (“conserve”). The point here is that a record does not create an asset, but is in a way itself an asset!
Example 2: Conditional Exchanges
In addition to creating custom assets, users can program death predicates of records to enforce conditions on how assets can be consumed, and thus realising a conditional exchange with other parties.
If Alice wishes to exchange 100 units of an asset with id_1 for an equivalent 50 units of asset id_2, she creates a record r with 100 units of id_1 whose death predicate stipulates that any transaction tx consuming r must also create another record, consumable only by Alice with 50 units of asset id_2.
She then publishes out of band information about r for anyone to subsequently claim it by creating a transaction in which the exchange is carried out.
By design, death predicates are arbitrary and thus various access policies can be realised. For example, a user can enforce that a transaction redeeming a record
- must be authorised by two-of-three public keys (i.e., using some multi-party computation),
- becomes valid only after a given amount of time has lapsed since its creation (using time-locks), or
- must reveal the pre-image of a hash function.
Transactions under the RNK
In ZEXE, generating a transaction involves creating commitments to new records as well as computing unique serial numbers for consumed records (similar to ZCash). Importantly, each commitment to a record requires the record owner’s address public key ‘apk’ and the serial number nonce. Similarly, the serial number of the consumed record r cannot be created without both the serial number nonce r and the owner’s address secret key ‘ask’. The serial number nonce of r is actually an output of a collision-resistant hash function that takes some unique transaction information that created r .
Note that the address secret key ‘ask’ is always taken as an input when the address public key ‘apk’ is generated. A transaction in Bitcoin or Zcash, for instance, allows a user to spend a coin only if she is in possession of the secret key. In ZEXE, the idea is much the same. What the RNK adds to the same condition for spending records is that all relevant predicates, set by the user who created the records to be spent, must be simultaneously satisfied.
The same conditions also govern the creation of zero-knowledge proofs that attests to correctness of the computation of the birth and death predicates over the provided local data. And therefore, if the user knows the secret keys of the records to be consumed and if all relevant predicates are satisfied, then the user can produce a zero knowledge proof to be appended to the transaction.
Figure 4: Illustrates the above description in more detail.
A Note About the RNK
The RNK is not a scripting mechanism, as in Bitcoin, but instead a framework that supports arbitrary programs. These programs can be run either as part of a single transaction, or across multiple transactions — by storing suitable intermediate state or message data in record payloads, or — by publishing that data in transaction memoranda (as plaintext or ciphertext as required).
Transactions can therefore realize any state transition, with consumed records as data read from the blockchain, and newly created records as data written back to the blockchain.
Heavy computations can be inevitable for some applications, which can cause problems for devices with limited computing capacity. To solve this problem, ZEXE provides another mode to DPC schemes: delegable DPC (or DDPC) schemes. This allows for time-consuming computations to be delegated to untrusted third parties. These third parties are given the necessary secrets to produce transactions, and submit the transactions back to the user, because the user does not disclose secrets needed to authorise transactions. The tradeoff of DDPC is that it no longer provides functional privacy. However, the operator cannot steal assets or deviate from the user’s signed intent in any way. So DDPC provides an additional option to speed up proof generation and computation time in exchange for slightly reduced privacy.
ZEXE was designed to enable private computation on public ledgers for arbitrary programs. This series of articles has focused on the context in which ZEXE is introduced among ledger-based systems, how transaction information has traditionally been handled in such systems, the number of technical problems that has plagued privacy-preserving ledger-based systems, the design techniques taken to eliminate these problems by the authors, and how these techniques can be implemented to achieve applications with true decentralisation, total privacy, as well as succinct verification.
The paradigm of decentralized private computation guarantees not only data but functional privacy. Execution occurs entirely offline, and published transactions are augmented with zero-knowledge proofs attesting to the correctness of the computation according to the birth/death predicates. Since the user-defined predicates are included in the statement being proved, under the zero-knowledge protocol, function calls are hidden and thus function privacy is achieved. Since these zero-knowledge proofs are succinct and verification is cheap, ZEXE also eliminates the Verifier’s Dilemma.
Beyond privacy, ZEXE’s approach also offers greater scalability compared to other ledger-based systems where the virtual machine is entirely on chain. Even more, newer cryptographic techniques such as recursive proofs composition potentially increase ZEXE’s scalability by orders of magnitude.
ZEXE aims to be a minimal, elegant protocol for supporting fully private applications. It extends prior ideas to achieve both privacy and programmability that heretofore have only been separately achieved by single-application systems. As a result, it provides an ideal platform for decentralized applications such as decentralized finance, gaming, authentication, and more. That’s why we chose to make ZEXE the basis of Aleo.