Snapps
Architecture
SnarkyJS
Hello World
Exercises
Wrap Up
(I)
(II)
(III)
(IV)
(V)
(I) Architecture
Mina Blockchain
22 KB
Fixed Size
Other Blockchains
350 GB
Increasing Size
Mina Blockchain
22 KB
Fixed Size
Ethereum dapps
Ethereum uses on-chain computation.
Mina snapps
Mina uses off-chain computation & on-chain verification.
Advantages
How does this work?
A “snapp” consists of two parts:
How does this work?
A SnarkyJS smart contract compiles down into 2 artifacts:
How does this work?
Deploying the verification key to the chain creates a “snapp account”.
How does this work?
Deploying the verification key to the chain creates a “snapp account”.
How does this work?
Deploying the verification key to the chain creates a “snapp account”.
Snapp methods
Each method of a snapp is actually compiled to a program which has
(II) SnarkyJS
SnarkyJS
Snapps are written in TypeScript using SnarkyJS.
Uses existing open technologies.
Field elements
Field elements
This can be simplified as:
In SnarkyJS, you would write this as:
In typical programming, you might use:
const sum = 1 + 3;
const sum = new Field(1).add(new Field(3));
const sum = new Field(1).add(3);
Other built-in types
SnarkyJS provides various useful types:
All have built-in methods on them.
Functions
Functions work as you would expect in TypeScript. For example:
function addOneAndDouble(x: Field): Field {
return x.add(1).mul(2);
}
function addOneAndDouble(x: Field): Field {
let xPlus1 = x.add(1);
return xPlus1.mul(2);
}
(III) Hello World
Getting set up
git clone https://github.com/o1-labs/snarkyjs-workshop.git
cd snarkyjs-workshop
npm install
Hello world
We’ll write a smart contract with a single state variable named x.
It will have a method update that will let us replace x with its square.
x = 3
update(9)
x = 9
update(81)
x = 81
x = 3
update(9)
x = 9
update(75)
Hello world
To write a snapp, extend the SmartContract class of SnarkyJS.
class HelloWorld extends SmartContract {
...
}
Hello world
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
}
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
}
Hello world
The constructor of a smart contract describes how it will be initialized when deployed.
Default parameters:
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
constructor(
initialBalance: UInt64,
address: PublicKey,
x: Field
) {
super(address);
this.balance.addInPlace(initialBalance);
this.x = State.init(x);
}
...
}
Hello world
A smart contract can contain multiple methods, each with its own logic.
The @methods of a smart contract describe how it can be invoked when deployed.
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
@method async update(squared: Field) {
const x = await this.x.get();
x.square().assertEquals(squared);
this.x.set(squared);
}
}
Hello world
The state of a snapp is public, unless explicitly stored as a commitment.
Any argument of a method is private, unless, for example, a method stores an argument directly in the state.
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
@method async update(squared: Field) {
const x = await this.x.get();
x.square().assertEquals(squared);
this.x.set(squared);
}
}
Hello world
The update method is async because it calls .get()
We run off chain, and so fetch the current state of the snapp account from the chain.
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
@method async update(squared: Field) {
const x = await this.x.get();
x.square().assertEquals(squared);
this.x.set(squared);
}
}
Under the hood
When we run update(9), we prove
“We ran the code in the update method with some arguments, and the result was
Updates:
set x to be 9
Assuming preconditions:
x = 3
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
...
@method async update(squared: Field) {
const x = await this.x.get();
x.square().assertEquals(squared);
this.x.set(squared);
}
}
x = 3
update(9)
x = 9
Summary: Anatomy of a smart contract
class HelloWorld extends SmartContract {
@state(Field) x: State<Field>;
constructor(
initialBalance: UInt64,
address: PublicKey,
x: Field
) {
...
}
@method async update(squared: Field) {
...
}
}
Running hello world
npx tsc && node dist/hello_world.js
(IV) Exercises
API exploration
You can explore the methods available using the API docs here:
docs.minaprotocol.com/en/snapps/snarkyjs-reference
Or by using autocomplete.
Exercises
For these exercises, we’ll use a mock Mina environment that runs locally.
Exercise 1
x = 3
update(27)
x = 27
update(19683)
x = 19683
x = 3
update(27)
x = 27
update(75)
Exercise 2: Hashing
Example: Payments
Payments review
Exercise 4: Functions and loops
for (let i = 0; i < 10; ++i) {
...
}
Exercise 5: Logic
and(y: Bool | boolean): Bool
or(y: Bool | boolean): Bool
not(): Bool
Circuit.if<T>(b: Bool | boolean, x: T, y: T): T
Exercise 5: Logic
Exercise 5 review: user-defined types
class SignatureWithSigner extends CircuitValue {
@prop signature: Signature;
@prop signer: PublicKey;
constructor(signature: Signature, signer: PublicKey) {
super();
this.signature = signature;
this.signer = signer;
}
}
Bonus: Recursion
What we didn’t cover
minaprotocol.com/snarkyjs
github.com/o1-labs/snarkyjs
@MinaProtocol
https://discord.com/invite/Vexf4ED
github.com/o1-labs/snapp-cli
@o1labs