Please note that zkApp programmability is not yet available on Mina Mainnet, but zkApps can now be deployed to Berkeley Testnet.
Basic concepts
Field
Field elements are the basic unit of data in zero-knowledge proof programming. Each field element can store a number up to almost 256 bits in size. You can think of it as a uint256 in Solidity.
For the cryptography inclined, the exact max value that a field can store 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
For example, in typical programming, you might use:
const sum = 1 + 3
.
In SnarkyJS, you write this as:
const sum = new Field(1).add(new Field(3))
This can be simplified as:
const sum = new Field(1).add(3)
Note that the 3 is auto-promoted to a field type to make this cleaner.
Built-in data types
Some common data types you may use are:
new Bool(x); // accepts true or false
new Field(x); // accepts an integer, or a numeric string if you want to represent a number greater than JavaScript can represent but within the max value that a field can store.
new UInt64(x); // accepts a Field - useful for constraining numbers to 64 bits
new UInt32(x); // accepts a Field - useful for constraining numbers to 32 bits
PrivateKey, PublicKey, Signature; // useful for accounts and signing
new Group(x, y); // a point on our elliptic curve, accepts two Fields/numbers/strings
Scalar; // the corresponding scalar field (different than Field)
CircuitString.from('some string'); // string of max length 128
In the case of Field
and Bool
, you can also call the constructor without new
:
let x = Field(10);
let b = Bool(true);
Conditionals
Traditional conditional statements are not yet supported by SnarkyJS:
// this will NOT work
if (foo) {
x.assertEquals(y);
}
Instead, use SnarkyJS’ built-in Circuit.if()
method, which is a ternary operator:
const x = Circuit.if(new Bool(foo), a, b); // behaves like `foo ? a : b`
Functions
Functions work as you would expect in TypeScript. For example:
function addOneAndDouble(x: Field): Field {
return x.add(1).mul(2);
}
Common methods
Some common methods you will use often are:
let x = new Field(4); // x = 4
x = x.add(3); // x = 7
x = x.sub(1); // x = 6
x = x.mul(3); // x = 18
x = x.div(2); // x = 9
x = x.square(); // x = 81
x = x.sqrt(); // x = 9
let b = x.equals(8); // b = Bool(false)
b = x.greaterThan(8); // b = Bool(true)
b = b.not().or(b).and(b); // b = Bool(true)
b.toBoolean(); // true
let hash = Poseidon.hash([x]); // takes array of Fields, returns Field
let privKey = PrivateKey.random(); // create a private key
let pubKey = PublicKey.fromPrivateKey(privKey); // derive public key
let msg = [hash];
let sig = Signature.create(privKey, msg); // sign a message
sig.verify(pubKey, msg); // Bool(true)
For a full list, see the SnarkyJS reference.