Comparing version 0.0.35 to 0.0.36
@@ -33,3 +33,3 @@ # Binary format for R1CS | ||
(a_{m-1,0}w_0 + a_{m-1,1}w_1 + ... + a_{m-1,n}w_{n}) &\cdot& (b_{m-1,0} w_0 + b_{m-1,1} w_1 + ... + b_{m-1,n} w_{n}) &-& (c_{m-1,0} w_0 + c_{m-1,1}w_1 + ... + c_{m-1,n}w_{n}) &=& 0 | ||
\end{array} \right. | ||
\end{array} \right. | ||
$$ | ||
@@ -118,3 +118,3 @@ | ||
Currently there are 3 types of sections defined: | ||
Currently there are 5 types of sections defined: | ||
@@ -124,2 +124,4 @@ * 0x00000001 : Header Section | ||
* 0x00000003 : Wire2LabelId Map Section | ||
* 0x00000004 : Custom gates List Section [UltraPlonk] | ||
* 0x00000005 : Custom gates Application Section [UltraPlonk] | ||
@@ -179,3 +181,3 @@ If the file contain other types, the format is valid, but they MUST be ignored. | ||
Size in bytes of a field element. Mast be a multiple of 8. | ||
Size in bytes of a field element. Must be a multiple of 8. | ||
@@ -378,3 +380,3 @@ Example: | ||
Total number of non Zero factors in the linear compination. | ||
Total number of non Zero factors in the linear combination. | ||
@@ -396,3 +398,3 @@ The factors MUST be sorted in ascending order. | ||
This is the factor that multiplies the associated wire in the linear convination. | ||
This is the factor that multiplies the associated wire in the linear combination. | ||
@@ -430,2 +432,79 @@ For example, to represent the linear combination: | ||
### Custom gates List Section [Plonk] | ||
Section Type: 0x04 | ||
```` | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ 4 ┃ Number of custom gates M ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
Custom gate 0 | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ N ┃ Custom gate template name ┃ Sequence of N 1-byte char ending with 0x0 | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Number of custom gate template parameters K ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Parameter 0 ┃ | ||
┃ 4 ┃ Parameter 2 ┃ | ||
┃ ... ┃ | ||
┃ 4 ┃ Parameter K-1 ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
... | ||
... | ||
... | ||
Custom gate M-1 | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ N ┃ Custom gate template name ┃ Sequence of N 1-byte char ending with 0x0 | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Custom gate template parameters K ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Parameter 0 ┃ | ||
┃ 4 ┃ Parameter 2 ┃ | ||
┃ ... ┃ | ||
┃ 4 ┃ Parameter K-1 ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
```` | ||
Custom gates are identified by the position in the list starting at index 0. | ||
### Custom gates Application Section [Plonk] | ||
Section Type: 0x05 | ||
```` | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ 4 ┃ Number of Custom gates applications N ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
Application 0 | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ 4 ┃ Custom gate identifier ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Number of signals S ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Signal 0 ┃ | ||
┃ 4 ┃ Signal 1 ┃ | ||
... | ||
┃ 4 ┃ Signal S-1 ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
... | ||
... | ||
... | ||
Application N-1 | ||
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ | ||
┃ 4 ┃ Custom gate identifier ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Number of signals S ┃ | ||
┣━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ | ||
┃ 4 ┃ Signal 0 ┃ | ||
┃ 4 ┃ Signal 1 ┃ | ||
... | ||
┃ 4 ┃ Signal S-1 ┃ | ||
┗━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ | ||
```` | ||
List of signals are inputs and outputs of the custom gate in the order they appear in the `CIRCOM` definition of the custom gate. | ||
## Rationale | ||
@@ -649,2 +728,1 @@ | ||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
@@ -8,3 +8,3 @@ { | ||
}, | ||
"version": "0.0.35", | ||
"version": "0.0.36", | ||
"description": "r1cs file format parser", | ||
@@ -40,10 +40,11 @@ "main": "./build/main.cjs", | ||
"@iden3/bigarray": "0.0.2", | ||
"@iden3/binfileutils": "0.0.10", | ||
"fastfile": "0.0.19", | ||
"ffjavascript": "0.2.48" | ||
"@iden3/binfileutils": "0.0.11", | ||
"fastfile": "0.0.20", | ||
"ffjavascript": "0.2.55" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^8.6.0", | ||
"mocha": "^10.0.0", | ||
"rollup": "^2.20.0" | ||
} | ||
} |
@@ -5,6 +5,22 @@ import {getCurveFromR} from "ffjavascript"; | ||
export const R1CS_FILE_HEADER_SECTION = 1; | ||
export const R1CS_FILE_CONSTRAINTS_SECTION = 2; | ||
export const R1CS_FILE_WIRE2LABELID_SECTION = 3; | ||
export const R1CS_FILE_CUSTOM_GATES_LIST_SECTION = 4; | ||
export const R1CS_FILE_CUSTOM_GATES_USES_SECTION = 5; | ||
export async function readR1csHeader(fd,sections,singleThread) { | ||
let options; | ||
if (typeof singleThread === "object") { | ||
options = singleThread; | ||
} else if (typeof singleThread === "undefined") { | ||
options= { | ||
singleThread: false, | ||
}; | ||
} else { | ||
options = { | ||
singleThread: singleThread, | ||
}; | ||
} | ||
const res = {}; | ||
@@ -16,3 +32,14 @@ await binFileUtils.startReadUniqueSection(fd, sections, 1); | ||
res.curve = await getCurveFromR(res.prime, singleThread); | ||
if (options.F) { | ||
if (options.F.p != res.prime) throw new Error("Different Prime"); | ||
res.F = options.F; | ||
} else if (options.getFieldFromPrime) { | ||
res.F = await options.getCurveFromPrime(res.prime, options.singleThread); | ||
} else if (options.getCurveFromPrime) { | ||
res.curve = await options.getCurveFromPrime(res.prime, options.singleThread); | ||
res.F = res.curve.Fr; | ||
} else { | ||
res.curve = await getCurveFromR(res.prime, options.singleThread); | ||
res.F = res.curve.Fr; | ||
} | ||
@@ -25,2 +52,5 @@ res.nVars = await fd.readULE32(); | ||
res.nConstraints = await fd.readULE32(); | ||
res.useCustomGates = typeof sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_LIST_SECTION] !== null | ||
&& typeof sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== "undefined" && sections[R1CS_FILE_CUSTOM_GATES_USES_SECTION] !== null; | ||
await binFileUtils.endReadSection(fd); | ||
@@ -32,2 +62,14 @@ | ||
export async function readConstraints(fd,sections, r1cs, logger, loggerCtx) { | ||
let options; | ||
if (typeof logger === "object") { | ||
options = logger; | ||
} else if (typeof logger === "undefined") { | ||
options= {}; | ||
} else { | ||
options = { | ||
logger: logger, | ||
loggerCtx: loggerCtx, | ||
}; | ||
} | ||
const bR1cs = await binFileUtils.readSection(fd, sections, 2); | ||
@@ -42,3 +84,3 @@ let bR1csPos = 0; | ||
for (let i=0; i<r1cs.nConstraints; i++) { | ||
if ((logger)&&(i%100000 == 0)) logger.info(`${loggerCtx}: Loading constraints: ${i}/${r1cs.nConstraints}`); | ||
if ((options.logger)&&(i%100000 == 0)) options.logger.info(`${options.loggerCtx}: Loading constraints: ${i}/${r1cs.nConstraints}`); | ||
const c = readConstraint(); | ||
@@ -71,3 +113,3 @@ constraints.push(c); | ||
const idx = buffV.getUint32(i*(4+r1cs.n8), true); | ||
const val = r1cs.curve.Fr.fromRprLE(buff, i*(4+r1cs.n8)+4); | ||
const val = r1cs.F.fromRprLE(buff, i*(4+r1cs.n8)+4); | ||
lc[idx] = val; | ||
@@ -80,2 +122,13 @@ } | ||
export async function readMap(fd, sections, r1cs, logger, loggerCtx) { | ||
let options; | ||
if (typeof logger === "object") { | ||
options = logger; | ||
} else if (typeof logger === "undefined") { | ||
options= {}; | ||
} else { | ||
options = { | ||
logger: logger, | ||
loggerCtx: loggerCtx, | ||
}; | ||
} | ||
const bMap = await binFileUtils.readSection(fd, sections, 3); | ||
@@ -91,3 +144,3 @@ let bMapPos = 0; | ||
for (let i=0; i<r1cs.nVars; i++) { | ||
if ((logger)&&(i%10000 == 0)) logger.info(`${loggerCtx}: Loading map: ${i}/${r1cs.nVars}`); | ||
if ((options.logger)&&(i%10000 == 0)) options.logger.info(`${options.loggerCtx}: Loading map: ${i}/${r1cs.nVars}`); | ||
const idx = readULE64(); | ||
@@ -112,10 +165,30 @@ map.push(idx); | ||
export async function readR1cs(fileName, loadConstraints, loadMap, singleThread, logger, loggerCtx) { | ||
let options; | ||
if (typeof loadConstraints === "object") { | ||
options = loadConstraints; | ||
} else if (typeof loadConstraints === "undefined") { | ||
options= { | ||
loadConstraints: true, | ||
loadMap: false, | ||
loadCustomGates: true | ||
}; | ||
} else { | ||
options = { | ||
loadConstraints: loadConstraints, | ||
loadMap: loadMap, | ||
singleThread: singleThread, | ||
logger: logger, | ||
loggerCtx: loggerCtx | ||
}; | ||
} | ||
if (typeof options.loadConstraints === "undefined") options.loadConstraints=true; | ||
if (typeof options.loadMap === "undefined") options.loadMap=false; | ||
if (typeof options.loadCustomGates === "undefined") options.loadCustomGates=true; | ||
const {fd, sections} = await binFileUtils.readBinFile(fileName, "r1cs", 1, 1<<25, 1<<22); | ||
const res = await readR1csHeader(fd, sections, singleThread); | ||
const res = await readR1csHeader(fd, sections, options); | ||
if (loadConstraints) { | ||
res.constraints = await readConstraints(fd, sections, res, logger, loggerCtx); | ||
if (options.loadConstraints) { | ||
res.constraints = await readConstraints(fd, sections, res, options); | ||
} | ||
@@ -125,6 +198,16 @@ | ||
if (loadMap) { | ||
res.map = await readMap(fd, sections, res, logger, loggerCtx); | ||
if (options.loadMap) { | ||
res.map = await readMap(fd, sections, res, options); | ||
} | ||
if(options.loadCustomGates) { | ||
if (res.useCustomGates) { | ||
res.customGates = await readCustomGatesListSection(fd, sections); | ||
res.customGatesUses = await readCustomGatesUsesSection(fd, sections); | ||
} else { | ||
res.customGates = []; | ||
res.customGatesUses = []; | ||
} | ||
} | ||
await fd.close(); | ||
@@ -135,3 +218,45 @@ | ||
export async function readCustomGatesListSection(fd, sections) { | ||
await binFileUtils.startReadUniqueSection(fd, sections, R1CS_FILE_CUSTOM_GATES_LIST_SECTION); | ||
let num = await fd.readULE32(); | ||
let customGates = []; | ||
for (let i = 0; i < num; i++) { | ||
let customGate = {}; | ||
customGate.templateName = await fd.readString(); | ||
let numParameters = await fd.readULE32(); | ||
customGate.parameters = []; | ||
for (let j = 0; j < numParameters; j++) { | ||
customGate.parameters.push(await fd.readULE32()); | ||
} | ||
customGates.push(customGate); | ||
} | ||
await binFileUtils.endReadSection(fd); | ||
return customGates; | ||
} | ||
export async function readCustomGatesUsesSection(fd, sections, options) { | ||
await binFileUtils.startReadUniqueSection(fd, sections, R1CS_FILE_CUSTOM_GATES_USES_SECTION); | ||
let num = await fd.readULE32(); | ||
let customGatesUses = []; | ||
for (let i = 0; i < num; i++) { | ||
if ((options.logger)&&(i%100000 == 0)) options.logger.info(`${options.loggerCtx}: Loading constraints: ${i}/${num}`); | ||
let customGatesUse = {}; | ||
customGatesUse.id = await fd.readULE32(); | ||
let numSignals = await fd.readULE32(); | ||
customGatesUse.signals = []; | ||
for (let j = 0; j < numSignals; j++) { | ||
customGatesUse.signals.push(await fd.readULE64()); | ||
} | ||
customGatesUses.push(customGatesUse); | ||
} | ||
await binFileUtils.endReadSection(fd); | ||
return customGatesUses; | ||
} | ||
export async function writeR1csHeader(fd, cir) { | ||
@@ -165,3 +290,3 @@ await binFileUtils.startWriteSection(fd, 1); | ||
const n8 = cir.n8; | ||
const F = cir.curve.Fr; | ||
const F = cir.F || cir.curve.Fr; | ||
const idxA = Object.keys(c[0]); | ||
@@ -227,3 +352,1 @@ const idxB = Object.keys(c[1]); | ||
} | ||
import * as r1cs from "../src/r1csfile.js"; | ||
import path from "path"; | ||
import assert from "assert"; | ||
import { Scalar } from "ffjavascript"; | ||
@@ -11,2 +10,3 @@ const primeStr = "21888242871839275222246405745257275088548364400416034343698204186575808495617"; | ||
"prime": primeStr, | ||
"useCustomGates": false, | ||
"nVars": 7, | ||
@@ -66,3 +66,5 @@ "nOutputs": 1, | ||
324 | ||
] | ||
], | ||
customGates: [], | ||
customGatesUses: [] | ||
}; | ||
@@ -92,3 +94,3 @@ | ||
it("Parse example file", async () => { | ||
let cir = await r1cs.readR1cs(path. join("test" , "testutils", "example.r1cs"), true, true); | ||
let cir = await r1cs.readR1cs(path.join("test" , "testutils", "example.r1cs"), true, true); | ||
@@ -98,2 +100,3 @@ const curve = cir.curve; | ||
delete cir.curve; | ||
delete cir.F; | ||
@@ -106,2 +109,19 @@ cir = stringifyBigInts(curve.Fr, cir); | ||
}); | ||
it("Parse example file with struct as second parameter", async () => { | ||
const struct = {loadConstraints: true, loadMap: true}; | ||
let cir = await r1cs.readR1cs(path. join("test" , "testutils", "example.r1cs"), struct); | ||
const curve = cir.curve; | ||
delete cir.Fr; | ||
delete cir.curve; | ||
delete cir.F; | ||
cir = stringifyBigInts(curve.Fr, cir); | ||
assert.deepEqual(cir, expected); | ||
await curve.terminate(); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
147317
16
763
3
+ Added@iden3/binfileutils@0.0.11(transitive)
+ Addedfastfile@0.0.20(transitive)
+ Addedffjavascript@0.2.55(transitive)
- Removed@iden3/binfileutils@0.0.10(transitive)
- Removedfastfile@0.0.19(transitive)
- Removedffjavascript@0.2.48(transitive)
Updated@iden3/binfileutils@0.0.11
Updatedfastfile@0.0.20
Updatedffjavascript@0.2.55