export-ton-verifier
Version:
Tool for generating Groth16 and PLONK verifier code for the TON blockchain from SnarkJS .zkey or verification key JSON files.
133 lines (117 loc) • 3.27 kB
text/typescript
import {
Address,
beginCell,
Cell,
Contract,
contractAddress,
ContractProvider,
Sender,
SendMode,
TupleItem,
Dictionary,
} from "@ton/core";
export type VerifierConfig = {};
export function verifierConfigToCell(config: VerifierConfig): Cell {
return beginCell().endCell();
}
export const Opcodes = {
verify: 0x3b3cca17,
};
export class Verifier implements Contract {
constructor(
readonly address: Address,
readonly init?: { code: Cell; data: Cell },
) {}
static createFromAddress(address: Address) {
return new Verifier(address);
}
static createFromConfig(config: VerifierConfig, code: Cell, workchain = 0) {
const data = verifierConfigToCell(config);
const init = { code, data };
return new Verifier(contractAddress(workchain, init), init);
}
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
await provider.internal(via, {
value,
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: beginCell().endCell(),
});
}
async sendVerify(
provider: ContractProvider,
via: Sender,
opts: {
pi_a: Buffer;
pi_b: Buffer;
pi_c: Buffer;
pubInputs: bigint[];
value: bigint;
queryID?: number;
},
) {
await provider.internal(via, {
value: opts.value,
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: this.buildVerifyBody(opts),
});
}
dictFromInputList(list: bigint[]): Dictionary<bigint, bigint> {
const dict: Dictionary<bigint, bigint> = Dictionary.empty(
Dictionary.Keys.BigUint(32),
Dictionary.Values.BigInt(256),
);
for (let i = 0; i < list.length; i++) {
dict.set(BigInt(i), list[i]);
}
return dict;
}
buildVerifyBody(opts: {
pi_a: Buffer;
pi_b: Buffer;
pi_c: Buffer;
pubInputs: bigint[];
}) {
const piAcell = beginCell().storeBuffer(opts.pi_a).endCell();
const piBcell = beginCell().storeBuffer(opts.pi_b).endCell();
const piCcell = beginCell().storeBuffer(opts.pi_c).endCell();
const pubDict = this.dictFromInputList(opts.pubInputs);
const body = beginCell()
.storeUint(Opcodes.verify, 32)
.storeRef(piAcell)
.storeRef(piBcell)
.storeRef(piCcell)
.storeDict(pubDict)
.endCell();
return body;
}
async getVerify(
provider: ContractProvider,
opts: {
pi_a: Buffer;
pi_b: Buffer;
pi_c: Buffer;
pubInputs: bigint[];
},
): Promise<boolean> {
const pi_a = {
type: "slice",
cell: beginCell().storeBuffer(opts.pi_a).endCell(),
} as TupleItem;
const pi_b = {
type: "slice",
cell: beginCell().storeBuffer(opts.pi_b).endCell(),
} as TupleItem;
const pi_c = {
type: "slice",
cell: beginCell().storeBuffer(opts.pi_c).endCell(),
} as TupleItem;
const pubInputs = {
type: "slice",
cell: beginCell()
.storeDict(this.dictFromInputList(opts.pubInputs))
.endCell(),
} as TupleItem;
const result = await provider.get("verify", [pi_a, pi_b, pi_c, pubInputs]);
return result.stack.readBoolean();
}
}