New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@guildofweavers/genstark

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@guildofweavers/genstark - npm Package Compare versions

Comparing version 0.6.3 to 0.7.0

128

genstark.d.ts

@@ -5,4 +5,4 @@ declare module '@guildofweavers/genstark' {

// --------------------------------------------------------------------------------------------
import { FiniteField } from '@guildofweavers/air-script';
import { BatchMerkleProof, HashAlgorithm } from '@guildofweavers/merkle';
import { AirSchema, FiniteField } from '@guildofweavers/air-assembly';
import { Hash, HashAlgorithm, BatchMerkleProof } from '@guildofweavers/merkle';

@@ -14,30 +14,75 @@ // RE-EXPORTS

// PUBLIC FUNCTIONS
// --------------------------------------------------------------------------------------------
/**
* Creates an instance of STARK object based on the provided AirAssembly schema.
* @param schema AirAssembly schema from which the STARK object is to be built.
* @param component Name of the component from which to instantiate STARK. If omitted 'default` will be used.
* @param options Security and optimization options for STARK instance.
* @param logger Optional logger; defaults to console logging; set to null to disable.
*/
export function instantiate(schema: AirSchema, component: string, options?: Partial<StarkOptions>, logger?: Logger | null): Stark;
/**
* Creates an instance of STARK object from the provided AirAssembly source code.
* @param source AirAssembly source code from which the STARK object is to be built.
* @param component Name of the component from which to instantiate STARK. If omitted 'default` will be used.
* @param options Security and optimization options for STARK instance.
* @param logger Optional logger; defaults to console logging; set to null to disable.
*/
export function instantiate(source: Buffer, component: string, options?: Partial<StarkOptions>, logger?: Logger | null): Stark;
/**
* Creates an instance of STARK object from the specified AirAssembly file.
* @param path Path to a file containing AirAssembly source code from which the STARK object is to be built.
* @param component Name of the component from which to instantiate STARK. If omitted 'default` will be used.
* @param options Security and optimization options for STARK instance.
* @param logger Optional logger; defaults to console logging; set to null to disable.
*/
export function instantiate(path: string, component: string, options?: Partial<StarkOptions>, logger?: Logger | null): Stark;
/**
* Creates an instance of STARK object from the provided AirScript source code.
* @param source AirScript source code from which the STARK object is to be built.
* @param options Security and optimization options for STARK instance.
* @param logger Optional logger; defaults to console logging; set to null to disable.
*/
export function instantiateScript(source: Buffer, options?: Partial<StarkOptions>, logger?: Logger): Stark;
/**
* Creates an instance of STARK object from the specified AirAssembly file.
* @param path Path to a file containing AirScript source code from which the STARK object is to be built.
* @param component Name of the component from which to instantiate STARK. If omitted 'default` will be used.
* @param logger Optional logger; defaults to console logging; set to null to disable.
*/
export function instantiateScript(path: string, options?: Partial<StarkOptions>, logger?: Logger): Stark;
// STARK
// --------------------------------------------------------------------------------------------
export interface StarkOptions extends SecurityOptions {
/** A flag indicating whether to use WebAssembly optimizations; defaults to true */
readonly wasm: boolean;
}
export interface SecurityOptions {
/**
* Execution trace extension factor; defaults to the smallest power of 2 greater than 2x
* of the highest constraint degree
*/
readonly extensionFactor: number;
/** Execution trace extension factor; defaults to the smallest power of 2 greater than 2x of max constraint degree */
extensionFactor: number;
/** Number of queries for the execution trace; defaults to 80 */
exeQueryCount: number;
readonly exeQueryCount: number;
/** Number of queries for low degree proof; defaults to 40 */
friQueryCount: number;
readonly friQueryCount: number;
/** Hash algorithm for Merkle trees; defaults to sha256 */
hashAlgorithm: HashAlgorithm;
readonly hashAlgorithm: HashAlgorithm;
}
export interface OptimizationOptions {
export interface Stark {
/** Initial number of bytes to allocate for WASM optimization */
initialMemory: number;
/** Maximum number of bytes to allocate for WASM optimization */
maximumMemory: number;
}
export class Stark {
/** Estimated security level of the STARK (experimental) */

@@ -47,36 +92,17 @@ readonly securityLevel: number;

/**
* Creates a STARK instance based on the provided parameters
* @param source AirScript source for the STARK
* @param security Security options for the STARK instance
* @param optimization A flag indicating whether WebAssembly-based optimization should be enabled
* @param logger Optional logger; defaults to console logging; set to null to disable
* Generate a proof of computation for this STARK.
* @param assertions Boundary constraints for the computation.
* @param inputs Values for initializing all declared input.
* @param seed Seed values for initializing execution trace.
*/
constructor(source: string, security?: Partial<SecurityOptions>, optimization?: boolean, logger?: Logger);
prove(assertions: Assertion[], inputs?: any[], seed?: bigint[]): StarkProof;
/**
* Creates a STARK instance based on the provided parameters
* @param source AirScript source for the STARK
* @param security Security options for the STARK instance
* @param optimization WebAssembly optimization options
* @param logger Optional logger; defaults to console logging; set to null to disable
* Verifies a proof of computation for this STARK.
* @param assertions Boundary constraints for the computation.
* @param proof Proof of the computation.
* @param publicInputs Values for initializing declared public inputs.
*/
constructor(source: string, security?: Partial<SecurityOptions>, optimization?: Partial<OptimizationOptions>, logger?: Logger);
verify(assertions: Assertion[], proof: StarkProof, publicInputs?: any[]): boolean;
/**
* Generate a proof of computation for this STARK
* @param assertions Boundary constraints for the computation
* @param inputs TODO
* @param auxPublicInputs TODO
* @param auxSecretInputs TODO
*/
prove(assertions: Assertion[], inputs: any[], auxPublicInputs?: bigint[][], auxSecretInputs?: bigint[][]): StarkProof;
/**
* Verifies a proof of computation for this STARK
* @param assertions Boundary constraints for the computation
* @param proof Proof of the computation
* @param auxPublicInputs TODO
*/
verify(assertions: Assertion[], proof: StarkProof, auxPublicInputs?: bigint[][]): boolean;
/** Returns the size in bytes for the provided proof */

@@ -93,6 +119,6 @@ sizeOf(proof: StarkProof): number;

export interface StarkProof {
evRoot : Buffer;
evProof : BatchMerkleProof;
ldProof : LowDegreeProof;
traceShape : number[];
evRoot : Buffer;
evProof : BatchMerkleProof;
ldProof : LowDegreeProof;
iShapes : number[][];
}

@@ -99,0 +125,0 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const air_assembly_1 = require("@guildofweavers/air-assembly");
const air_script_1 = require("@guildofweavers/air-script");
const Stark_1 = require("./lib/Stark");
const utils_1 = require("./lib/utils");
// RE-EXPORTS
// ================================================================================================
var Stark_1 = require("./lib/Stark");
exports.Stark = Stark_1.Stark;
var utils_1 = require("./lib/utils");
exports.inline = utils_1.inline;
var Stark_2 = require("./lib/Stark");
exports.Stark = Stark_2.Stark;
var utils_2 = require("./lib/utils");
exports.inline = utils_2.inline;
var merkle_1 = require("@guildofweavers/merkle");

@@ -14,2 +18,31 @@ exports.MerkleTree = merkle_1.MerkleTree;

exports.createPrimeField = galois_1.createPrimeField;
// PUBLIC FUNCTIONS
// ================================================================================================
function instantiate(source, component, options, logger) {
if (logger === null) {
logger = utils_1.noopLogger;
}
else if (logger === undefined) {
logger = new utils_1.Logger();
}
if (source instanceof air_assembly_1.AirSchema) {
return new Stark_1.Stark(source, component, options, logger);
}
else {
const schema = air_assembly_1.compile(source);
return new Stark_1.Stark(schema, component, options, logger);
}
}
exports.instantiate = instantiate;
function instantiateScript(source, options, logger) {
if (logger === null) {
logger = utils_1.noopLogger;
}
else if (logger === undefined) {
logger = new utils_1.Logger();
}
const schema = air_script_1.compile(source);
return instantiate(schema, 'default', options, logger);
}
exports.instantiateScript = instantiateScript;
//# sourceMappingURL=index.js.map

@@ -11,3 +11,3 @@ "use strict";

// --------------------------------------------------------------------------------------------
constructor(constraints, assertions, seed, context, logger) {
constructor(assertions, seed, context, logger) {
this.field = context.field;

@@ -18,9 +18,9 @@ this.bPoly = new BoundaryConstraints_1.BoundaryConstraints(assertions, context);

// degree of trace polynomial combination
this.combinationDegree = getCombinationDegree(constraints, context.traceLength);
this.combinationDegree = getCombinationDegree(context.constraints, context.traceLength);
// degree of composition polynomial is deg(C(x)) = deg(Q(x)) - deg(Z(x))
this.compositionDegree = Math.max(this.combinationDegree - context.traceLength, context.traceLength);
// group transition constraints together by their degree
this.constraintGroups = groupTransitionConstraints(constraints, context.traceLength);
this.constraintGroups = groupTransitionConstraints(context.constraints, context.traceLength);
// create coefficients needed for linear combination
let dCoefficientCount = constraints.length;
let dCoefficientCount = context.constraints.length;
for (let { degree, indexes } of this.constraintGroups) {

@@ -51,3 +51,3 @@ if (degree < this.combinationDegree) {

try {
qEvaluations = context.evaluateTracePolynomials(pPolys);
qEvaluations = context.evaluateTransitionConstraints(pPolys);
}

@@ -54,0 +54,0 @@ catch (error) {

@@ -12,5 +12,4 @@ "use strict";

this.fieldElementSize = config.field.elementSize;
this.stateWidth = config.stateWidth;
this.iRegisterCount = config.iRegisterCount;
this.sRegisterCount = config.sRegisterCount;
this.tRegisterCount = config.traceRegisterCount;
this.sRegisterCount = config.secretInputCount;
this.hashDigestSize = hashDigestSize;

@@ -46,6 +45,9 @@ }

}
// trace shape
offset = buffer.writeUInt8(proof.traceShape.length, offset);
for (let level of proof.traceShape) {
offset = buffer.writeUInt32LE(level, offset);
// input shapes
offset = buffer.writeUInt8(proof.iShapes.length, offset);
for (let shape of proof.iShapes) {
offset = buffer.writeUInt8(shape.length, offset);
for (let level of shape) {
offset = buffer.writeUInt32LE(level, offset);
}
}

@@ -90,9 +92,14 @@ // return the buffer

}
// trace shape
const traceDepth = buffer.readUInt8(offset);
// input shapes
const inputCount = buffer.readUInt8(offset);
offset += 1;
const traceShape = new Array(traceDepth);
for (let i = 0; i < traceDepth; i++) {
traceShape[i] = buffer.readUInt32LE(offset);
offset += 4;
const inputShapes = new Array(inputCount);
for (let i = 0; i < inputCount; i++) {
let rank = buffer.readUInt8(offset);
offset += 1;
inputShapes[i] = new Array();
for (let j = 0; j < rank; j++) {
inputShapes[i][j] = buffer.readUInt32LE(offset);
offset += 4;
}
}

@@ -109,3 +116,3 @@ // build and return the proof

},
traceShape: traceShape
iShapes: inputShapes
};

@@ -116,3 +123,3 @@ }

getValueCount() {
return this.stateWidth + this.sRegisterCount + this.iRegisterCount;
return this.tRegisterCount + this.sRegisterCount;
}

@@ -119,0 +126,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const merkle_1 = require("@guildofweavers/merkle");
const air_script_1 = require("@guildofweavers/air-script");
const air_assembly_1 = require("@guildofweavers/air-assembly");
const components_1 = require("./components");

@@ -15,5 +15,2 @@ const utils_1 = require("./utils");

const MAX_FRI_QUERY_COUNT = 64;
const WASM_PAGE_SIZE = 65536; // 64 KB
const DEFAULT_INITIAL_MEMORY = 32 * 2 ** 20; // 32 MB
const DEFAULT_MAXIMUM_MEMORY = 2 * 2 ** 30 - WASM_PAGE_SIZE; // 2 GB less one page
const HASH_ALGORITHMS = ['sha256', 'blake2s256'];

@@ -26,33 +23,20 @@ const DEFAULT_HASH_ALGORITHM = 'sha256';

// --------------------------------------------------------------------------------------------
constructor(source, security, optimization, logger) {
if (typeof source !== 'string')
throw new TypeError('Source script must be a string');
if (!source.trim())
throw new TypeError('Source script cannot be an empty string');
let extensionFactor = security ? security.extensionFactor : undefined;
let sOptions;
if (optimization) {
const wasmOptions = buildWasmOptions(optimization);
// instantiate AIR module
this.air = air_script_1.parseScript(source, { wasmOptions, extensionFactor });
if (!this.air.field.isOptimized) {
console.warn(`WARNING: WebAssembly optimization is not available for the specified field`);
}
// instantiate Hash object
sOptions = validateSecurityOptions(security, this.air.extensionFactor);
const wasmOptions2 = buildWasmOptions(optimization); // TODO: use the same options as for AIR
this.hash = merkle_1.createHash(sOptions.hashAlgorithm, wasmOptions2);
if (!this.hash.isOptimized) {
console.warn(`WARNING: WebAssembly optimization is not available for ${sOptions.hashAlgorithm} hash algorithm`);
}
constructor(schema, component, options = {}, logger) {
const wasmOptions = buildWasmOptions(options.wasm);
// instantiate AIR module
this.air = air_assembly_1.instantiate(schema, component, { extensionFactor: options.extensionFactor, wasmOptions });
if (wasmOptions && !this.air.field.isOptimized) {
console.warn(`WARNING: WebAssembly optimization is not available for the specified field`);
}
else {
this.air = air_script_1.parseScript(source, { extensionFactor });
sOptions = validateSecurityOptions(security, this.air.extensionFactor);
this.hash = merkle_1.createHash(sOptions.hashAlgorithm, false);
// build security options
const sOptions = buildSecurityOptions(options, this.air.extensionFactor);
// instantiate Hash object
this.hash = merkle_1.createHash(sOptions.hashAlgorithm, this.air.field.isOptimized);
if (!this.hash.isOptimized) {
console.warn(`WARNING: WebAssembly optimization is not available for ${sOptions.hashAlgorithm} hash algorithm`);
}
this.extensionFactor = sOptions.extensionFactor;
;
this.indexGenerator = new components_1.QueryIndexGenerator(sOptions);
this.serializer = new Serializer_1.Serializer(this.air, this.hash.digestSize);
this.logger = logger || new utils_1.Logger();
this.logger = logger;
}

@@ -62,3 +46,3 @@ // ACCESSORS

get securityLevel() {
const extensionFactor = this.extensionFactor;
const extensionFactor = this.air.extensionFactor;
// execution trace security

@@ -76,3 +60,3 @@ const exeQueryCount = this.indexGenerator.exeQueryCount;

// --------------------------------------------------------------------------------------------
prove(assertions, inputs, auxPublicInputs, auxSecretInputs) {
prove(assertions, inputs, seed) {
const log = this.logger.start('Starting STARK computation');

@@ -84,7 +68,4 @@ // 0 ----- validate parameters

throw new TypeError('At least one assertion must be provided');
if (!Array.isArray(inputs))
throw new TypeError('Initialization values parameter must be an array');
// 1 ----- set up evaluation context
const field = this.air.field;
const context = this.air.initProof(inputs, auxPublicInputs || [], auxSecretInputs || []);
const context = this.air.initProvingContext(inputs, seed);
const evaluationDomainSize = context.evaluationDomain.length;

@@ -103,9 +84,9 @@ log('Set up evaluation context');

// 3 ----- compute P(x) polynomials and low-degree extend them
const pPolys = field.interpolateRoots(context.executionDomain, executionTrace);
const pPolys = context.field.interpolateRoots(context.executionDomain, executionTrace);
log('Computed execution trace polynomials P(x)');
const pEvaluations = field.evalPolysAtRoots(pPolys, context.evaluationDomain);
const pEvaluations = context.field.evalPolysAtRoots(pPolys, context.evaluationDomain);
log('Low-degree extended P(x) polynomials over evaluation domain');
// 4 ----- build merkle tree for evaluations of P(x) and S(x)
const hEvaluations = context.hiddenRegisterTraces;
const eVectors = [...field.matrixRowsToVectors(pEvaluations), ...hEvaluations];
const sEvaluations = context.secretRegisterTraces;
const eVectors = [...context.field.matrixRowsToVectors(pEvaluations), ...sEvaluations];
const hashedEvaluations = this.hash.mergeVectorRows(eVectors);

@@ -117,3 +98,3 @@ log('Serialized evaluations of P(x) and S(x) polynomials');

const cLogger = this.logger.sub('Computing composition polynomial');
const cPoly = new components_1.CompositionPolynomial(this.air.constraints, assertions, eTree.root, context, cLogger);
const cPoly = new components_1.CompositionPolynomial(assertions, eTree.root, context, cLogger);
const cEvaluations = cPoly.evaluateAll(pPolys, pEvaluations, context);

@@ -124,3 +105,3 @@ this.logger.done(cLogger);

const lCombination = new components_1.LinearCombination(eTree.root, cPoly.compositionDegree, cPoly.coefficientCount, context);
const lEvaluations = lCombination.computeMany(cEvaluations, pEvaluations, hEvaluations);
const lEvaluations = lCombination.computeMany(cEvaluations, pEvaluations, sEvaluations);
log('Combined P(x) and S(x) evaluations with C(x) evaluations');

@@ -152,3 +133,3 @@ // 7 ----- Compute low-degree proof

ldProof: ldProof,
traceShape: context.traceShape
iShapes: context.inputShapes
};

@@ -158,3 +139,3 @@ }

// --------------------------------------------------------------------------------------------
verify(assertions, proof, auxPublicInputs) {
verify(assertions, proof, publicInputs) {
const log = this.logger.start('Starting STARK verification');

@@ -165,8 +146,7 @@ // 0 ----- validate parameters

// 1 ----- set up evaluation context
const field = this.air.field;
const eRoot = proof.evRoot;
const extensionFactor = this.extensionFactor;
const context = this.air.initVerification(proof.traceShape, auxPublicInputs || []);
const extensionFactor = this.air.extensionFactor;
const context = this.air.initVerificationContext(proof.iShapes, publicInputs);
const evaluationDomainSize = context.traceLength * extensionFactor;
const cPoly = new components_1.CompositionPolynomial(this.air.constraints, assertions, eRoot, context, utils_1.noop);
const cPoly = new components_1.CompositionPolynomial(assertions, eRoot, context, utils_1.noop);
const lCombination = new components_1.LinearCombination(eRoot, cPoly.compositionDegree, cPoly.coefficientCount, context);

@@ -180,9 +160,9 @@ log('Set up evaluation context');

const pEvaluations = new Map();
const hEvaluations = new Map();
const sEvaluations = new Map();
for (let i = 0; i < proof.evProof.values.length; i++) {
let mergedEvaluations = proof.evProof.values[i];
let position = augmentedPositions[i];
let [p, h] = this.parseValues(mergedEvaluations);
let [p, s] = this.parseValues(mergedEvaluations);
pEvaluations.set(position, p);
hEvaluations.set(position, h);
sEvaluations.set(position, s);
}

@@ -208,10 +188,10 @@ log(`Decoded evaluation spot checks`);

let step = positions[i];
let x = field.exp(context.rootOfUnity, BigInt(step));
let x = context.field.exp(context.rootOfUnity, BigInt(step));
let pValues = pEvaluations.get(step);
let nValues = pEvaluations.get((step + extensionFactor) % evaluationDomainSize);
let hValues = hEvaluations.get(step);
let sValues = sEvaluations.get(step);
// evaluate composition polynomial at x
let cValue = cPoly.evaluateAt(x, pValues, nValues, hValues, context);
let cValue = cPoly.evaluateAt(x, pValues, nValues, sValues, context);
// combine composition polynomial evaluation with values of P(x) and S(x)
lcValues[i] = lCombination.computeOne(x, cValue, pValues, hValues);
lcValues[i] = lCombination.computeOne(x, cValue, pValues, sValues);
}

@@ -246,3 +226,3 @@ log(`Verified transition and boundary constraints`);

getAugmentedPositions(positions, evaluationDomainSize) {
const skip = this.extensionFactor;
const skip = this.air.extensionFactor;
const augmentedPositionSet = new Set();

@@ -269,15 +249,12 @@ for (let i = 0; i < positions.length; i++) {

const elementSize = this.air.field.elementSize;
const stateWidth = this.air.stateWidth;
const sRegisterCount = this.air.sRegisterCount;
const iRegisterCount = this.air.iRegisterCount;
let offset = 0;
const pValues = new Array(stateWidth);
const pValues = new Array(this.air.traceRegisterCount);
for (let i = 0; i < pValues.length; i++, offset += elementSize) {
pValues[i] = utils_1.readBigInt(buffer, offset, elementSize);
}
const hValues = new Array(sRegisterCount + iRegisterCount);
for (let i = 0; i < hValues.length; i++, offset += elementSize) {
hValues[i] = utils_1.readBigInt(buffer, offset, elementSize);
const sValues = new Array(this.air.secretInputCount);
for (let i = 0; i < sValues.length; i++, offset += elementSize) {
sValues[i] = utils_1.readBigInt(buffer, offset, elementSize);
}
return [pValues, hValues];
return [pValues, sValues];
}

@@ -288,3 +265,3 @@ }

// ================================================================================================
function validateSecurityOptions(options, extensionFactor) {
function buildSecurityOptions(options, extensionFactor) {
// execution trace spot checks

@@ -311,17 +288,11 @@ const exeQueryCount = (options ? options.exeQueryCount : undefined) || DEFAULT_EXE_QUERY_COUNT;

}
function buildWasmOptions(options) {
if (typeof options === 'boolean') {
return {
memory: new WebAssembly.Memory({
initial: Math.ceil(DEFAULT_INITIAL_MEMORY / WASM_PAGE_SIZE),
maximum: Math.ceil(DEFAULT_MAXIMUM_MEMORY / WASM_PAGE_SIZE)
})
};
}
else {
const initialMemory = Math.ceil((options.initialMemory || DEFAULT_INITIAL_MEMORY) / WASM_PAGE_SIZE);
const maximumMemory = Math.ceil((options.maximumMemory || DEFAULT_MAXIMUM_MEMORY) / WASM_PAGE_SIZE);
const memory = new WebAssembly.Memory({ initial: initialMemory, maximum: maximumMemory });
return { memory };
}
function buildWasmOptions(useWasm) {
if (useWasm === false)
return undefined;
return {
memory: new WebAssembly.Memory({
initial: 512,
maximum: 32768 // 2 GB
})
};
}

@@ -328,0 +299,0 @@ function validateAssertions(trace, assertions) {

@@ -14,2 +14,3 @@ "use strict";

exports.Logger = Logger_1.Logger;
exports.noopLogger = Logger_1.noopLogger;
exports.inline = inliners;

@@ -16,0 +17,0 @@ // MATH

@@ -59,2 +59,10 @@ "use strict";

exports.Logger = Logger;
// NOOP LOGGER
// ================================================================================================
const noopLog = (message) => undefined;
exports.noopLogger = {
start: (message, prefix) => noopLog,
sub: (message) => noopLog,
done: (log, message) => undefined
};
//# sourceMappingURL=Logger.js.map

@@ -32,7 +32,10 @@ "use strict";

size += ldProof;
// trace shape
let traceShape = 1; // trace depth
traceShape += proof.traceShape.length * 4;
size += traceShape;
return { evProof, ldProof: { lcProof, levels: ldLevels, total: ldProof }, traceShape, total: size };
// input shapes
let inputShapes = 1; // input count
for (let i = 0; i < proof.iShapes.length; i++) {
inputShapes += 1; // rank
inputShapes += proof.iShapes[i].length * 4;
}
size += inputShapes;
return { evProof, ldProof: { lcProof, levels: ldLevels, total: ldProof }, inputShapes, total: size };
}

@@ -39,0 +42,0 @@ exports.sizeOf = sizeOf;

{
"name": "@guildofweavers/genstark",
"version": "0.6.3",
"version": "0.7.0",
"description": "zk-STARK generation library",

@@ -24,9 +24,17 @@ "main": "index.js",

},
"scripts": {
"clean": "rimraf bin",
"compile": "tsc -p .",
"copyfiles": "copyfiles ./package*.json ./*.d.ts ./*.md ./.npmignore bin",
"build": "npm run clean && npm run copyfiles && npm run compile",
"publish": "npm publish bin --access=public"
},
"devDependencies": {
"@types/node": "12.7.x",
"del": "5.0.x",
"gulp": "4.0.x"
"copyfiles": "2.1.x",
"rimraf": "3.0.x"
},
"dependencies": {
"@guildofweavers/air-script": "0.5.x",
"@guildofweavers/air-assembly": "0.3.x",
"@guildofweavers/air-script": "0.6.x",
"@guildofweavers/galois": "0.4.x",

@@ -33,0 +41,0 @@ "@guildofweavers/merkle": "0.3.x"

@@ -19,13 +19,15 @@ # genSTARK

```TypeScript
import { Stark } from '@guildofweavers/genstark';
import { instantiateScript } from '@guildofweavers/genstark';
// define a STARK for this computation
const fooStark = new Stark(`
const fooStark = instantiateScript(Buffer.from(`
define Foo over prime field (2^32 - 3 * 2^25 + 1) {
secret input startValue: element[1];
// define transition function
transition 1 register {
for each ($i0) {
init { $i0 }
for steps [1..63] { $r0 + 2 }
for each (startValue) {
init { yield startValue; }
for steps [1..63] { yield $r0 + 2; }
}

@@ -36,5 +38,5 @@ }

enforce 1 constraint {
for all steps { transition($r) = $n }
for all steps { enforce transition($r) = $n; }
}
}`);
}`));

@@ -96,90 +98,84 @@ // create a proof that if we start computation at 1, we end up at 127 after 64 steps

To create a STARK for a computation you need to create a `Stark` object like so:
The simplest way to create a STARK for a computation is to instantiate it from [AirScript](https://github.com/GuildOfWeavers/AirScript) source like so:
```TypeScript
const myStark = new Stark(source, security, optimization, logger);
const myStark = new instantiateScript(source, options, logger);
```
where:
* `source` is the AirScript source code. If this parameter is a `Buffer`, it is expected to contain AirScript code in UTF8 format. If the parameter is a string, it is expected to be a path to a file containing AirScript code.
* `options` is an optional parameter with additional [STARK options](#Stark-options).
* `logger` is an optional logger. The default logger prints output to the console, but it can be replaced with anything that complies with the Logger interface.
The meaning of the constructor parameters is as follows:
### STARK options
When provided, STARK options parameter should have the following form:
| Parameter | Description |
| ------------------ | ----------- |
| source | [AirScript](https://github.com/GuildOfWeavers/AirScript) source defining transition function, transition constraints, and other properties of the STARK. |
| security? | An optional property specifying [security parameters](#Security-options) for the STARK. |
| optimization? | An optional property specifying [WASM optimization parameters](#Optimization-options) for the STARK. You can also set this to `true` to turn on WASM optimization with default parameters. |
| logger? | An optional logger. The default logger prints output to the console, but it can be replaced with anything that complies with the Logger interface. |
**Note:** WASM-optimization is available for certain [finite fields](https://github.com/GuildOfWeavers/galois#wasm-optimization) and [hash functions](https://github.com/GuildOfWeavers/merkle#hash). If the field or the hash function you are using does not support WASM-optimization, a warning will be printed and its JavaScript equivalents will be used. In general, WASM optimization can speed up STARK proof time by 2x - 5x.
### Security options
Security options parameter should have the following form:
| Property | Description |
| ------------------ | ----------- |
| extensionFactor? | Number by which the execution trace is "stretched." Must be a power of 2 at least 2x of the constraint degree, but cannot exceed 32. This property is optional, the default is smallest power of 2 that is greater than 2 * constraint degree. |
| exeQueryCount? | Number of queries of the execution trace to include into the proof. This property is optional; the default is 80; the max is 128. |
| exeQueryCount? | Number of queries of the execution trace to include into the proof. This property is optional; the default is 80; the max is 128. |
| friQueryCount? | Number of queries of the columns of low degree proof to include into the proof. This property is optional; the default is 40; the max is 64. |
| hashAlgorithm? | Hash algorithm to use when building Merkle trees for the proof. Currently, can be one of the following values: `sha256`, `blake2s256`. This property is optional; the default is `sha256`. |
| wasm | A flag indicating whether to use WebAssembly optimizations. This proper is optional, the default is `true`. |
### Optimization options
Optimization options parameter should have the following form:
**Note:** WASM-optimization is available for certain [finite fields](https://github.com/GuildOfWeavers/galois#wasm-optimization) and [hash functions](https://github.com/GuildOfWeavers/merkle#hash). If the field or the hash function you are using does not support WASM-optimization, a warning will be printed and its JavaScript equivalents will be used. In general, WASM optimization can speed up STARK proof time by 2x - 5x.
| Property | Description |
| ------------------ | ----------- |
| initialMemory? | Initial number of bytes to allocate for WASM optimization; the default is 32 MB. |
| maximumMemory? | Maximum number of bytes to allocate for WASM optimization; the default is 2 GB. |
You can also instantiate a STARK from [AirAssembly](https://github.com/GuildOfWeavers/AirAssembly) source, or even from an [AirSchema](https://github.com/GuildOfWeavers/AirAssembly#air-schema) object:
```TypeScript
const myStark = new instantiate(source, component, options, logger);
```
where:
* `source` is either `Buffer` with AirAssembly source code, a string that is a path to a file with AirAssembly source code, or an `AirSchema` object.
* `component` is a name of the component within AirAssembly source from which the STARK is to be instantiated. If this parameter is omitted the `default` component will be instantiated.
* `options` is an optional parameter with additional [STARK options](#Stark-options).
* `logger` is an optional logger. The default logger prints output to the console, but it can be replaced with anything that complies with the Logger interface.
## Generating proofs
Once you have a `Stark` object, you can start generating proofs using `Stark.prove()` method like so:
```TypeScript
const proof = myStark.prove(assertions, initValues, publicInputs?, secretInputs?);
const proof = myStark.prove(assertions, inputs?, seed?);
```
The meaning of the parameters is as follows:
where:
* `assertions` is an array of [Assertion](#Assertions) objects (also called boundary constraints). These assertions specify register values at specific steps of a valid computation. At least 1 assertion must be provided.
* `inputs` is an array of values initializing all declared inputs. This parameter must be provided only if the STARK requires inputs.
* `seed` is an array of seed values for initializing execution trace. This parameter must be provided only if the STARK requires initialization from seed values.
| Parameter | Description |
| ------------- | ----------- |
| assertions | An array of [Assertion](#Assertions) objects (also called boundary constraints). These assertions specify register values at specific steps of a valid computation. At least 1 assertion must be provided. |
| inputs | An array containing initialization values for all `$i` registers. Must contain at least one set of values. |
| auxPublicInputs? | An array containing initialization values for all `$p` registers. This parameter is optional and can be skipped if no public auxiliary inputs have been defined. |
| auxSecretInputs? | An array containing initialization values for all `$s` registers. This parameter is optional and can be skipped if no secret auxiliary inputs have been defined. |
### Inputs
Handling of inputs deserves a bit more explanation. As described above, there are 3 ways to supply inputs to `STARK.prove()` method:
Handling of inputs deserves a bit more explanation.
* `inputs` parameter is always required. It is used to initialize the execution trace for different instances of the computation. The structure of `inputs` must match the structure of input loops defined in transition function. For more information, see [Input loops](https://github.com/GuildOfWeavers/AirScript#input-loops) section of AirScript documentation.
* The other two parameters provide values for the input registers defined in the STARK. To learn more about these, refer to [Readonly registers](https://github.com/GuildOfWeavers/AirScript#readonly-registers) section of AirScript documentation. These parameters are required only if STARK's definition includes auxiliary input registers.
If you've instantiated a STARK from AirScrip source, you don't need to worry about the `seed` parameter as AirScript does not support explicit trace initialization. However, STARKs instantiated from AirScript source always require `inputs` parameter. The shape of this parameter will depend on how you've defined your inputs (see [AirScript](https://github.com/GuildOfWeavers/AirScript#inputs) documentation for more info).
For example, the fragment below specifies that a STARK must have a single `$i` register of depth 0, and 3 auxiliary input registers. Moreover, prefixes `$p` and `$s` specify that 2 of the auxiliary registers are *public* (the values will be known to the prover **and** the verified), and 1 of the registers is *secret* (the values will be known **only** to the prover).
For example, if your input declaration looks like this:
```
transition 1 register {
for each ($i0) {
init { $i0 }
for steps [1..63] { $r0 + 2 }
}
}
public input foo: element[1];
```
your `inputs` array will need to contain a single element which will be an array of values for input `foo`. For example:
```TypeScript
[[1n, 2n]]
```
using 3 readonly registers {
$p0: repeat [...];
$p1: spread [...];
$s0: spread [...];
}
If you've declared more than one input, like so:
```
Based on this definition, the parameters for `STARK.prove()` method should be supplied like so:
public input foo: element[1];
public input bar: element[1];
```
your `inputs` array will need to contain an array of values for each declared input. For example:
```TypeScript
// let's say we want to run the computation for 2 sets of inputs
let inputs = [[1n], [2n]];
[[1n, 2n], [3n, 4n]]
```
Here, the `[1n, 2n]` values are assigned to input `foo` and `[3n, 4n]` values are assigned to input `bar`.
// define values for public auxiliary inputs
let pValues1 = [1n, 2n, 3n, 4n];
let pValues2 = [1n, 2n, 3n, 4n, 5n, 6n, 7n, 7n];
// define values for secret auxiliary inputs
let sValues = [10n, 11n, 12n, 13n];
// generate the proof
let proof = fooStark.prove(assertions, inputs, [pValues1, pValues2], [sValues]);
If you've declared [nested inputs](https://github.com/GuildOfWeavers/AirScript#nested-input-loops) like so:
```
When the proof is generated, the provided values will "appear" in registers `$i0`, `$p0`, `$p1`, and `$s0` to be used in transition function and transition constraints. The rules for how this happens are also described in the [Input loops](https://github.com/GuildOfWeavers/AirScript#input-loops) and [Readonly registers](https://github.com/GuildOfWeavers/AirScript#readonly-registers) sections of AirScript documentation.
public input foo: element[1];
public input bar: element[1][1];
```
your `inputs` object may look like so:
```TypeScript
[[1n, 2n], [[3n, 4n], [5n, 6n]]]
```
Here, for each value of `foo`, we need to provide a list of value for `bar`.
#### AirAssembly inputs
If you've instantiated a STARK from AirAssembly source, you may need to provide values for both `inputs` and `seed` parameters based on what is required by AirAssembly declaration. The `inputs` parameter requirements are defined via [input registers](https://github.com/GuildOfWeavers/AirAssembly/tree/master/specs#input-registers), while `seed` parameter requirements are defined via [trace initializer](https://github.com/GuildOfWeavers/AirAssembly/tree/master/specs#trace-initializer).

@@ -190,12 +186,9 @@ ## Verifying proofs

```TypeScript
const result = myStark.verify(assertions, proof, auxPublicInputs?);
const result = myStark.verify(assertions, proof, publicInputs?);
```
The meaning of the parameters is as follows:
where:
* `assertions` is the same array of [Assertion](#Assertions) objects that was passed to the `prove()` method.
* `proof` is the proof object that was generated by the `prove()` method.
* `publicInputs` is an array of values for initializing all declared public inputs.
| Parameter | Description |
| ------------- | ----------- |
| assertions | The same array of [Assertion](#Assertions) objects that was passed to the `prove()` method. |
| proof | The proof object that was generated by the `prove()` method. |
| auxPublicInputs? | An array containing initialization values for all `$p` registers. This parameter is optional and can be skipped if no public auxiliary inputs have been defined. |
Verifying a proof basically attests to something like this:

@@ -202,0 +195,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc