Skip to content

Commit

Permalink
adding tests to getGroth16Calldata
Browse files Browse the repository at this point in the history
  • Loading branch information
luiz-lvj committed Nov 2, 2024
1 parent 85134d6 commit 0330a64
Show file tree
Hide file tree
Showing 11 changed files with 1,678 additions and 304 deletions.
6 changes: 6 additions & 0 deletions tools/npm/garaga_ts/babel.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-typescript',
],
};
11 changes: 7 additions & 4 deletions tools/npm/garaga_ts/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
export default {
module.exports= {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/tests/**/*.test.ts'],
moduleFileExtensions: ['ts', 'js'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
// transform: {
// '^.+\\.ts$': 'ts-jest'
// },
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts'],
transform: {
'^.+\\.(ts|tsx|js|jsx)$': 'babel-jest',
},
};
1,838 changes: 1,566 additions & 272 deletions tools/npm/garaga_ts/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions tools/npm/garaga_ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"test:watch": "jest --watch"
},
"devDependencies": {
"@babel/preset-env": "^7.26.0",
"@babel/preset-typescript": "^7.26.0",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jest": "^29.5.13",
"@types/node": "^22.7.4",
Expand Down
9 changes: 1 addition & 8 deletions tools/npm/garaga_ts/src/node/api.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// This files provides a ts-like interface for garaga_rs

import { msm_calldata_builder, mpc_calldata_builder, to_twistededwards, to_weirstrass, get_groth16_calldata } from '../wasm/pkg/garaga_rs';
import { CurveId } from './definitions';
import { Groth16Proof, Groth16VerifyingKey } from './starknet/groth16ContractGenerator/parsingUtils';

export enum CurveId {
BN254 = 0,
BLS12_381 = 1,
SECP256K1 = 2,
SECP256R1 = 3,
X25519 = 4,
}

export type G1Point = [bigint, bigint];
export type G2Point = [[bigint, bigint], [bigint, bigint]];
export type G1G2Pair = [G1Point, G2Point];
Expand Down
13 changes: 11 additions & 2 deletions tools/npm/garaga_ts/src/node/hints/io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,13 @@ export const bitLength = (x: bigint): number => {
}

export const split128 = (a: bigint): [bigint, bigint] => {
const MAX_UINT256 = BigInt(2) ** BigInt(256);
const MASK_128 = BigInt((1n << BigInt(128)) - 1n);
try{

console.log("a bigint", a);

const MAX_UINT256 = 115792089237316195423570985008687907853269984665640564039457584007913129639936n;

const MASK_128 = BigInt((1n << 128n) - 1n);

if (a < 0n || a >= MAX_UINT256) {
throw new Error(`Value ${a} is too large to fit in a u256`);
Expand All @@ -91,6 +96,10 @@ export const split128 = (a: bigint): [bigint, bigint] => {
const high = a >> BigInt(128);

return [low, high];
} catch(err){
console.log("ERR split 128: ", err);
throw new Error("ERROR split 128")
}
}

export const modInverse = (a: bigint, p: bigint): bigint => {
Expand Down
3 changes: 3 additions & 0 deletions tools/npm/garaga_ts/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
export * from './api'; // exports "ts" interface
export * from '../wasm/pkg/garaga_rs'; // export "raw" interface

export { CurveId } from './definitions';

import pkg_init from '../wasm/pkg/garaga_rs';
import module_or_path from '../wasm/pkg/garaga_rs_bg.wasm';


export function init(): ReturnType<typeof pkg_init> {
return pkg_init({ module_or_path });
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export const parseGroth16ProofFromObject = (data: any, publicInputsData?: bigint
const imageIdBytes = hexStringToBytes(imageIdHex);
const journalBytes = hexStringToBytes(journalHex);


return createGroth16ProofFromRisc0(sealBytes, imageIdBytes, journalBytes)

} catch(err){
Expand All @@ -228,7 +229,7 @@ export const parseGroth16ProofFromObject = (data: any, publicInputsData?: bigint
try {
publicInputs = findItemFromKeyPatterns(data, ['public']);
} catch(err){
throw new Error(`Error: ${err}`);

}
}
const a = tryParseG1PointFromKey(proof, ['a'], curveId);
Expand Down Expand Up @@ -258,21 +259,26 @@ export const parseGroth16ProofFromObject = (data: any, publicInputsData?: bigint
export const createGroth16ProofFromRisc0 = (seal: Uint8Array, imageId: Uint8Array, journalBytes: Uint8Array,
controlRoot: bigint = RISC0_CONTROL_ROOT, bn254ControlId: bigint = RISC0_BN254_CONTROL_ID): Groth16Proof => {


if(imageId.length > 32){
throw new Error("imageId must be 32 bytes")
}

const [constrolRoot0, controlRoot1] = splitDigest(controlRoot);
const [controlRoot0, controlRoot1] = splitDigest(controlRoot);

const proof = seal.slice(4);



const journal = createHash("sha256").update(journalBytes).digest();

const claimDigest = digestReceiptClaim(ok(imageId, journal));


const [claim0, claim1] = splitDigest(claimDigest);



const groth16Proof: Groth16Proof = {
a: {
x: toBigInt(proof.slice(0, 32)),
Expand All @@ -282,7 +288,7 @@ export const createGroth16ProofFromRisc0 = (seal: Uint8Array, imageId: Uint8Arra
b: {
x: [
toBigInt(proof.slice(96, 128)),
toBigInt(proof.slice(64, 196))
toBigInt(proof.slice(64, 96))
],
y: [
toBigInt(proof.slice(160, 192)),
Expand All @@ -296,7 +302,7 @@ export const createGroth16ProofFromRisc0 = (seal: Uint8Array, imageId: Uint8Arra
curveId: CurveId.BN254
},
publicInputs: [
constrolRoot0,
controlRoot0,
controlRoot1,
claim0,
claim1,
Expand All @@ -311,7 +317,6 @@ export const createGroth16ProofFromRisc0 = (seal: Uint8Array, imageId: Uint8Arra

throw new Error(`Invalid Groth16 proof: ${groth16Proof}`);


}


Expand Down Expand Up @@ -344,19 +349,30 @@ export const checkGroth16VerifyingKey = (vk: Groth16VerifyingKey): boolean => {

const digestReceiptClaim = (receipt: ReceiptClaim): Uint8Array => {
const { tagDigest, input, preStateDigest, postStateDigest, output, exitCode } = receipt;

const systemExitCodeBuffer = Buffer.alloc(4);
systemExitCodeBuffer.writeUInt32BE(exitCode.system << 24);

const userExitCodeBuffer = Buffer.alloc(4);
userExitCodeBuffer.writeUInt32BE(exitCode.user << 24);

// Create a 2-byte big-endian representation of 4 << 8
const twoBytes = Buffer.alloc(2);
twoBytes.writeUInt16BE(4 << 8);


// Concatenating all parts into one Buffer
const data = Buffer.concat([
tagDigest!,
input,
preStateDigest,
postStateDigest,
output,
Buffer.alloc(4, exitCode.system << 24), // Encode exitCode.system in 4 bytes, big-endian
Buffer.alloc(4, exitCode.user << 24), // Encode exitCode.user in 4 bytes, big-endian
Buffer.alloc(2, 4 << 8) // Add the 4 << 8 equivalent to (4 << 8).to_bytes(2, 'big')
systemExitCodeBuffer,
userExitCodeBuffer,
twoBytes
]);

// Return the sha256 digest of the combined data
return createHash('sha256').update(data).digest();
}

Expand Down Expand Up @@ -390,19 +406,22 @@ function ok(imageId: Uint8Array, journalDigest: Uint8Array): ReceiptClaim {
const digestOutput = (output: Output): Uint8Array =>{
const { journalDigest, assumptionsDigest } = output;


// Compute the internal tag digest equivalent to hashlib.sha256(b"risc0.Output").digest()
const tagDigest = createHash('sha256').update(Buffer.from("risc0.Output")).digest();

// Concatenate all parts into a single Buffer
const data = Buffer.concat([
tagDigest,
journalDigest,
assumptionsDigest,
Buffer.alloc(2, 2 << 8) // Add the 2 << 8 equivalent to (2 << 8).to_bytes(2, 'big')
const twoBytes = Buffer.alloc(2);
twoBytes.writeUInt16BE(512);

const combined = Buffer.concat([
tagDigest,
Buffer.from(journalDigest),
Buffer.from(assumptionsDigest),
twoBytes // Append 2 as a 2-byte big-endian integer
]);

// Return the sha256 digest of the combined data
return createHash('sha256').update(data).digest();
return createHash('sha256').update(combined).digest();
}

const reverseByteOrderUint256 = (value: bigint | Uint8Array): bigint => {
Expand Down
45 changes: 45 additions & 0 deletions tools/npm/garaga_ts/tests/starknet/groth16Calldata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Groth16Proof, parseGroth16ProofFromJson, parseGroth16VerifyingKeyFromJson } from "../../src/node/starknet/groth16ContractGenerator/parsingUtils";
import * as garaga from "../../src/node/index";


const PATH = '../../../hydra/garaga/starknet/groth16_contract_generator/examples';

describe('Groth16 Getting calldata', () => {

const proofAndVkWithPublicInputs = [
[`${PATH}/proof_bn254.json`, `${PATH}/vk_bn254.json`, null],
[`${PATH}/proof_bls.json`, `${PATH}/vk_bls.json`, null],

[`${PATH}/gnark_proof_bn254.json`, `${PATH}/gnark_vk_bn254.json`, `${PATH}/gnark_public_bn254.json`],
[`${PATH}/snarkjs_proof_bn254.json`, `${PATH}/snarkjs_vk_bn254.json`, `${PATH}/snarkjs_public_bn254.json`],

[`${PATH}/proof_risc0.json`, `${PATH}/vk_risc0.json`, null],

]

test.each(proofAndVkWithPublicInputs)("should get groth16 calldata from proof %s, vk %s and pub inputs %s", async (proofPath, vkPath, pubInputsPath) => {

await garaga.init();

const vk = parseGroth16VerifyingKeyFromJson(vkPath as string);

let proof: Groth16Proof;
if(pubInputsPath == null){
proof = parseGroth16ProofFromJson(proofPath as string);
} else{
proof = parseGroth16ProofFromJson(proofPath as string, pubInputsPath);
}

const curveId: garaga.CurveId = proof.a.curveId;

console.log("proof", proof);

console.log("vk", vk);
console.log("curveId", curveId);
const groth16Calldata = garaga.getGroth16CallData(proof, vk, curveId);

console.log("groth16Calldata", groth16Calldata);

});

});
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ describe('Groth16 Parsing Tests', () => {

const proofPaths = [
`${PATH}/proof_bn254.json`,
`${PATH}/proof_bls.json`,
`${PATH}/proof_risc0.json`
`${PATH}/proof_bls.json`
];

test.each(proofPaths)('should parse proof from %s', (proofPath) => {
Expand Down
1 change: 1 addition & 0 deletions tools/npm/garaga_ts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"noPropertyAccessFromIndexSignature": true,
"types": ["jest", "node"],
"skipLibCheck": true, // Skipping type checks for external libraries
"esModuleInterop": true
},
"include": ["src/**/*.ts", "tests/**/*.ts"]
}

0 comments on commit 0330a64

Please sign in to comment.