Skip to content

Instantly share code, notes, and snippets.

@liamzebedee
Created July 23, 2022 07:15
Show Gist options
  • Select an option

  • Save liamzebedee/f0ec887683824caae6dd5a48cdac0c0f to your computer and use it in GitHub Desktop.

Select an option

Save liamzebedee/f0ec887683824caae6dd5a48cdac0c0f to your computer and use it in GitHub Desktop.
import { SelfProof, Field, ZkProgram, verify, Poseidon, SmartContract, Scalar, arrayProp } from 'snarkyjs';
import {
Circuit,
CircuitValue,
prop,
public_,
circuitMain,
Signature,
PrivateKey,
PublicKey,
} from 'snarkyjs';
class Wallet {
constructor(
public pubKey: PublicKey,
public privKey: PrivateKey
) {
}
static createRandom() {
let privKey = PrivateKey.random();
let pubKey = PublicKey.fromPrivateKey(privKey);
return new Wallet(pubKey, privKey)
}
// send(to: PublicKey, amount: Field) {
// let tx = new Transaction(
// this.pubKey,
// to,
// amount
// )
// let hash = Poseidon.hash(tx.toFields());
// let msg = [hash];
// let sig = Signature.create(this.privKey, msg);
// return [msg, sig]
// }
}
let account1 = Wallet.createRandom()
let account2 = Wallet.createRandom()
// Create a tx that sends 100 COIN from account1 to account2.
// account1.send(account2.pubKey, Field.fromNumber(100))
/*
A coin looks like this:
Coin (owner, amount)
You spend a coin as input, and create two coins as outputs
input: Coin()
outputs: Coin()
sig
*/
class Coin extends CircuitValue {
@prop amount: Field
@prop owner: PublicKey
constructor(amount: Field, owner: PublicKey) {
super();
this.amount = amount;
this.owner = owner;
}
static from(obj: any): Coin {
return new Coin(obj.amount, obj.owner)
}
}
class RawTransaction extends CircuitValue {
@prop inputIdx: Field;
@arrayProp(Coin, 5) outputs: Coin[];
constructor(input: Field, outputs: Coin[]) {
super();
this.inputIdx = input;
this.outputs = outputs;
}
sighash() {
return Poseidon.hash(this.toFields())
}
}
class Transaction extends CircuitValue {
@prop inputIdx: Field;
@prop sig: Signature;
@arrayProp(Coin, 5) outputs: Coin[];
constructor(input: Field, outputs: Coin[]) {
super();
this.inputIdx = input;
this.sig = SIGNATURE_NULL;
this.outputs = outputs;
}
sighash() {
return (new RawTransaction(this.inputIdx, this.outputs)).sighash()
}
sign(privKey: PrivateKey) {
let msg = [this.sighash()]
let sig = Signature.create(privKey, msg);
this.sig = sig
}
// sigHash() {
// let data = [
// this.inputIdx,
// ...this.outputs.flatMap(output => ([ output.amount, ...output.owner.toFields() ]))
// ]
// return Poseidon.hash(data)
// }
}
function fieldToNumber(field: Field): number {
return parseInt(field.toString())
}
let Minicoin = ZkProgram({
publicInput: Transaction,
methods: {
genesis: {
privateInputs: [],
method(t1: Transaction) {
// Genesis.
// (new Field(t1.outputs.length)).assertEquals(1)
t1.outputs[0].amount.assertEquals(new Field(1000))
// t1.outputs[0]..assertEquals(Field(1000))
}
},
transfer: {
privateInputs: [SelfProof],
method(t1: Transaction, t0: SelfProof<Transaction>) {
// Verify the sequence is correct.
// Verify the state at t=0 was computed correctly.
t0.verify();
// Verify the state at t=1.
// This is the core of the state machine.
// Perform transfer of the coin.
// Verify input coin.
// A1: select an output coin of the previous tx.
const prevNumOutputs = t0.publicInput.outputs.length
t1.inputIdx.assertLt(prevNumOutputs)
const uxto = t0.publicInput.outputs[fieldToNumber(t1.inputIdx)]
// A2: the transfer is from the owner of this uxto.
const hash = t1.sighash()
const msg = [hash];
t1.sig.verify(uxto.owner, msg)
// Verify output coins.
// A3: input == sum(outputs)
let sumOutputs = Field.zero
for (const output of t1.outputs) {
sumOutputs.add(output.amount)
}
uxto.amount.assertEquals(sumOutputs)
},
},
},
});
let Proof = ZkProgram.Proof(Minicoin);
console.log('compiling Minicoin...');
const { verificationKey } = await Minicoin.compile();
const SIGNATURE_NULL = new Signature(Field.zero, new Scalar())
let genesisTx = new Transaction(
Field.zero,
[
Coin.from({ amount: new Field(1000), owner: account1.pubKey })
]
)
// console.log(genesisTx)
console.log('Genesis...');
let genesis = await Minicoin.genesis(genesisTx)
console.log('transfer #1...');
let input = genesis
let inputIdx = Field.zero
let outputs = [
{
amount: new Field(500),
owner: account1.pubKey,
},
{
amount: new Field(500),
owner: account2.pubKey,
}
].map(Coin.from)
let tx = new Transaction(inputIdx, outputs)
tx.sign(account1.privKey)
let proof = await Minicoin.transfer(tx, genesis);
proof.verify()
@liamzebedee

Copy link
Copy Markdown
Author
TypeError: Cannot read property 'amount' of undefined
    at method (file:///Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/src/examples/simple_quark.tmp.mjs:96:23)
    at main (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:3862:5)
    at caml_call2 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:615)
    at v_ (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4906638)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4034531
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at br (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3255867)
    at caml_call2 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:615)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4034481
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at br (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3255867)
    at caml_call2 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:615)
    at B0 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4034364)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at X (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4039027)
    at caml_call_gen (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39189)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39442
    at caml_call_gen (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39136)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:548)
    at $a (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3253969)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3256290
    at caml_call_gen (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39189)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39442
    at caml_call_gen (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2:39136)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:548)
    at U (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3247158)
    at caml_call2 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:615)
    at K_ (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3194887)
    at D_ (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3195191)
    at caml_call4 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:777)
    at kr (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3256310)
    at caml_call3 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:693)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4039057
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at time (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3860151)
    at we (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4030241)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at w (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:3326812)
    at caml_call1 (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:4:543)
    at r_ (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4039316)
    at compile_promise (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4072891)
    at Function.pickles_compile (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/node_bindings/snarky_js_node.bc.js:2215:4909421)
    at Function.Class.<computed> [as compile] (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:601:52)
    at /Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:3829:144
    at withContext (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:3465:14)
    at compileProgram (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:3829:75)
    at Object.compile (/Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/dist/server/index.js:3743:78)
    at file:///Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/src/examples/simple_quark.tmp.mjs:120:42
    at ModuleJob.run (node:internal/modules/esm/module_job:175:25)
    at async Loader.import (node:internal/modules/esm/loader:178:24)
    at async buildAndImport (file:///Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/src/build/buildExample.mjs:12:22)
    at async file:///Users/liamz/Documents/Projects/shard/cairo/research/snarky/snarkyjs/src/build/run.mjs:20:14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment