zkApp programmability is not yet available on the Mina Mainnet. You can get started now by deploying zkApps to the Berkeley Testnet.
o1js Basic Concepts
o1js, fka. SnarkyJS, is a TypeScript (TS) library for writing general-purpose ZK programs and writing ZK smart contracts for the Mina Blockchain. In order to create a ZKP (zero knowledge proof), you should use types and operations that can be converted into a ZKP. o1js gives you a lot of different built in types and customizable structures that you can use to create ZKPs.
Field Type
Field
elements are the basic unit of data in ZK programming. Every other data type (either built-in or composite) in o1js is made up of Field
elements.
Each Field
element can store a number up to almost 256 bits in size. You can think of it as a uint256
in Solidity, but there are some fundamental differences explained below.
For the cryptography inclined, the prime order of the o1js Field
is: 28,948,022,309,329,048,855,892,746,252,171,976,963,363,056,481,941,560,715,954,676,764,349,967,630,336
Creating a Field Element
You can create a Field
either with the new
constructor or by directly calling the Field
as a constructor. The best practice is to use Field
without the new
constructor.
const x = new Field(42);
const y = Field(923); // Best practice
You can create a Field
from anything that is "field-like": number
, string
, bigint
, or another Field
. Note that the argument you give must be an integer in the Field
range.
const x = Field("12347"); // From string
const y = Field(172384782343434n); // From bigint
const z = Field(x); // From another Field
const k = Field("asdf"); // Throws, as this is not a number
const l = Field("234.34"); // Throws, as this is not an integer
Nevertheless, you can create a Field
from a negative number. This method implicity calculates the modular inverse of the given argument. This is an advanced level information, and you do not need it for simple zkApps.
const x = Field(-1); // If you try printing this to the screen, you will see a very big integer
Methods in the Field Type
Field
type includes a lot of built in methods. You can call all methods in the Field
type either with a Field
or with a "field-like" value. In the latter case, the argument is implicity converted to a Field
.
All common arithmetic operations exist in the Field
type. They create and return a new Field
element.
const x = Field(45);
const y = Field(78);
const sum = x.add(y);
const sub = x.sub(y);
const mul = x.mul(47); // You can also use "field-like" values
const div = x.div(89); // This is a modular division
const neg = x.neg(); // This is equivalent to x.mul(-1)
const square = x.square(); // x^2, equivalent to x.mul(x)
const sqrt = x.sqrt(); // Modular square root of x
const inv = x.inv(); // Modular inverse of x
You can also perform logical operations and comparisons with Field
elements. These methods return a Bool element, which is another common o1js built in type, equivalent to boolean
in other languages and frameworks.
const x = Field(45);
x.equals(45); // True
x.greaterThan(45); // False
x.greaterThanOrEquals(45); // True
x.lessThan(45); // False
x.lessThanOrEquals(45); // True
// It is also possible to check if a Field is even or not
x.isEven(); // False
Assertions in o1js
If you want to reject a TX (transaction) in your zkApp smart contract, you can use assertions in o1js. If you create an assertion inside your ZKP, the proof fails if the assertion does not evaluate to true
. All conditional methods on the Field
type can be used as assertions.
const x = Field(45);
x.assertEquals(45); // True - passes
x.assertGreaterThan(45); // False - throws
x.assertGreaterThanOrEquals(45); // True - passes
x.assertLessThan(45); // False - throws
x.assertLessThanOrEquals(45); // True - passes
You can think assertions in o1js similar to require()
function in Solidity.
Printing a Field to the Screen
Field
elements are stored as classes in o1js. This is why if you print a Field
without a conversion, you will get an unreadable output. Hopefully, o1js gives a variety of conversion methods to print Field
elements to the screen.
const x = Field(45);
console.log(x.toString()); // string
console.log(x.toBigInt()); // bigint
console.log(x.toJSON()); // JSON string
However, note that these methods are not provable, meaning you cannot use them in your final zkApp as a part of the ZKP. Use them only to debug your code.
const x = Field(45);
const y = Field(x.toString()); // You should NOT write this
Other Types and Methods
In addition to the Field
type, o1js gives you a variety structures to help you build a powerful zkApp. You can learn more about them in the next chapter, Common Types and Functions.