@ -1,3 +1,3 @@ |
|||
module.exports.compiler = require("./src/compiler.js"); |
|||
module.exports.c_tester = require("./src/c_tester.js"); |
|||
module.exports.tester = require("./src/c_tester.js"); |
|||
module.exports.c_tester = require("./ports/c/tester.js"); |
|||
module.exports.wasm_tester = require("./ports/wasm/tester.js"); |
@ -0,0 +1,439 @@ |
|||
<% function signL(reg, label_pos, label_neg) { %> |
|||
<% for (let i=n64-1; i>=0; i--) { %> |
|||
mov rax, [<%=reg%> + <%= 8+(i*8) %>] |
|||
cmp [half + <%= (i*8) %>], rax ; comare with (q-1)/2 |
|||
jc <%=label_neg%> ; half<rax => e1-e2 is neg => e1 < e2 |
|||
<% if (i>0) { %> |
|||
jnz <%=label_pos%> ; half>rax => e1 -e2 is pos => e1 > e2 |
|||
<% } else { %> |
|||
jmp <%=label_pos%> |
|||
<% } %> |
|||
<% } %> |
|||
<% } %> |
|||
|
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; rgt - Raw Greater Than |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; returns in ax 1 id *rsi > *rdx |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rax <= Return 1 or 0 |
|||
; Modified Registers: |
|||
; r8, r9, rax |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_rgt: |
|||
mov r8, [rsi] |
|||
mov r9, [rdx] |
|||
bt r8, 63 ; Check if is short first operand |
|||
jc rgt_l1 |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc rgt_s1l2 |
|||
|
|||
rgt_s1s2: ; Both operands are short |
|||
cmp r8d, r9d |
|||
jg rgt_ret1 |
|||
jmp rgt_ret0 |
|||
|
|||
|
|||
rgt_l1: |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc rgt_l1l2 |
|||
|
|||
;;;;;;;; |
|||
rgt_l1s2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc rgt_l1ms2 |
|||
rgt_l1ns2: |
|||
<%= global.toLong_b() %> |
|||
jmp rgtL1L2 |
|||
|
|||
rgt_l1ms2: |
|||
<%= global.toLong_b() %> |
|||
<%= global.fromMont_a() %> |
|||
jmp rgtL1L2 |
|||
|
|||
|
|||
;;;;;;;; |
|||
rgt_s1l2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rgt_s1l2m |
|||
rgt_s1l2n: |
|||
<%= global.toLong_a() %> |
|||
jmp rgtL1L2 |
|||
|
|||
rgt_s1l2m: |
|||
<%= global.toLong_a() %> |
|||
<%= global.fromMont_b() %> |
|||
jmp rgtL1L2 |
|||
|
|||
;;;; |
|||
rgt_l1l2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc rgt_l1ml2 |
|||
rgt_l1nl2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rgt_l1nl2m |
|||
rgt_l1nl2n: |
|||
jmp rgtL1L2 |
|||
|
|||
rgt_l1nl2m: |
|||
<%= global.fromMont_b() %> |
|||
jmp rgtL1L2 |
|||
|
|||
rgt_l1ml2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rgt_l1ml2m |
|||
rgt_l1ml2n: |
|||
<%= global.fromMont_a() %> |
|||
jmp rgtL1L2 |
|||
|
|||
rgt_l1ml2m: |
|||
<%= global.fromMont_a() %> |
|||
<%= global.fromMont_b() %> |
|||
jmp rgtL1L2 |
|||
|
|||
|
|||
;;;;;; |
|||
; rgtL1L2 |
|||
;;;;;; |
|||
|
|||
rgtL1L2: |
|||
<%= signL("rsi", "rgtl1l2_p1", "rgtl1l2_n1") %> |
|||
rgtl1l2_p1: |
|||
<%= signL("rdx", "rgtRawL1L2", "rgt_ret1") %> |
|||
|
|||
rgtl1l2_n1: |
|||
<%= signL("rdx", "rgt_ret0", "rgtRawL1L2") %> |
|||
|
|||
|
|||
rgtRawL1L2: |
|||
<% for (let i=n64-1; i>=0; i--) { %> |
|||
mov rax, [rsi + <%= 8+(i*8) %>] |
|||
cmp [rdx + <%= 8+(i*8) %>], rax ; comare with (q-1)/2 |
|||
jc rgt_ret1 ; rsi<rdx => 1st > 2nd |
|||
<% if (i>0) { %> |
|||
jnz rgt_ret0 |
|||
<% } %> |
|||
<% } %> |
|||
|
|||
rgt_ret0: |
|||
xor rax, rax |
|||
ret |
|||
rgt_ret1: |
|||
mov rax, 1 |
|||
ret |
|||
|
|||
|
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; rlt - Raw Less Than |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; returns in ax 1 id *rsi > *rdx |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rax <= Return 1 or 0 |
|||
; Modified Registers: |
|||
; r8, r9, rax |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_rlt: |
|||
mov r8, [rsi] |
|||
mov r9, [rdx] |
|||
bt r8, 63 ; Check if is short first operand |
|||
jc rlt_l1 |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc rlt_s1l2 |
|||
|
|||
rlt_s1s2: ; Both operands are short |
|||
cmp r8d, r9d |
|||
jl rlt_ret1 |
|||
jmp rlt_ret0 |
|||
|
|||
|
|||
rlt_l1: |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc rlt_l1l2 |
|||
|
|||
;;;;;;;; |
|||
rlt_l1s2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc rlt_l1ms2 |
|||
rlt_l1ns2: |
|||
<%= global.toLong_b() %> |
|||
jmp rltL1L2 |
|||
|
|||
rlt_l1ms2: |
|||
<%= global.toLong_b() %> |
|||
<%= global.fromMont_a() %> |
|||
jmp rltL1L2 |
|||
|
|||
|
|||
;;;;;;;; |
|||
rlt_s1l2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rlt_s1l2m |
|||
rlt_s1l2n: |
|||
<%= global.toLong_a() %> |
|||
jmp rltL1L2 |
|||
|
|||
rlt_s1l2m: |
|||
<%= global.toLong_a() %> |
|||
<%= global.fromMont_b() %> |
|||
jmp rltL1L2 |
|||
|
|||
;;;; |
|||
rlt_l1l2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc rlt_l1ml2 |
|||
rlt_l1nl2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rlt_l1nl2m |
|||
rlt_l1nl2n: |
|||
jmp rltL1L2 |
|||
|
|||
rlt_l1nl2m: |
|||
<%= global.fromMont_b() %> |
|||
jmp rltL1L2 |
|||
|
|||
rlt_l1ml2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc rlt_l1ml2m |
|||
rlt_l1ml2n: |
|||
<%= global.fromMont_a() %> |
|||
jmp rltL1L2 |
|||
|
|||
rlt_l1ml2m: |
|||
<%= global.fromMont_a() %> |
|||
<%= global.fromMont_b() %> |
|||
jmp rltL1L2 |
|||
|
|||
|
|||
;;;;;; |
|||
; rltL1L2 |
|||
;;;;;; |
|||
|
|||
rltL1L2: |
|||
<%= signL("rsi", "rltl1l2_p1", "rltl1l2_n1") %> |
|||
rltl1l2_p1: |
|||
<%= signL("rdx", "rltRawL1L2", "rlt_ret0") %> |
|||
|
|||
rltl1l2_n1: |
|||
<%= signL("rdx", "rlt_ret1", "rltRawL1L2") %> |
|||
|
|||
|
|||
rltRawL1L2: |
|||
<% for (let i=n64-1; i>=0; i--) { %> |
|||
mov rax, [rsi + <%= 8+(i*8) %>] |
|||
cmp [rdx + <%= 8+(i*8) %>], rax ; comare with (q-1)/2 |
|||
jc rlt_ret0 ; rsi<rdx => 1st > 2nd |
|||
jnz rlt_ret1 |
|||
<% } %> |
|||
|
|||
rlt_ret0: |
|||
xor rax, rax |
|||
ret |
|||
rlt_ret1: |
|||
mov rax, 1 |
|||
ret |
|||
|
|||
|
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; req - Raw Eq |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; returns in ax 1 id *rsi == *rdx |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rax <= Return 1 or 0 |
|||
; Modified Registers: |
|||
; r8, r9, rax |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_req: |
|||
mov r8, [rsi] |
|||
mov r9, [rdx] |
|||
bt r8, 63 ; Check if is short first operand |
|||
jc req_l1 |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc req_s1l2 |
|||
|
|||
req_s1s2: ; Both operands are short |
|||
cmp r8d, r9d |
|||
je req_ret1 |
|||
jmp req_ret0 |
|||
|
|||
|
|||
req_l1: |
|||
bt r9, 63 ; Check if is short second operand |
|||
jc req_l1l2 |
|||
|
|||
;;;;;;;; |
|||
req_l1s2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc req_l1ms2 |
|||
req_l1ns2: |
|||
<%= global.toLong_b() %> |
|||
jmp reqL1L2 |
|||
|
|||
req_l1ms2: |
|||
<%= global.toMont_b() %> |
|||
jmp reqL1L2 |
|||
|
|||
|
|||
;;;;;;;; |
|||
req_s1l2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc req_s1l2m |
|||
req_s1l2n: |
|||
<%= global.toLong_a() %> |
|||
jmp reqL1L2 |
|||
|
|||
req_s1l2m: |
|||
<%= global.toMont_a() %> |
|||
jmp reqL1L2 |
|||
|
|||
;;;; |
|||
req_l1l2: |
|||
bt r8, 62 ; check if montgomery first |
|||
jc req_l1ml2 |
|||
req_l1nl2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc req_l1nl2m |
|||
req_l1nl2n: |
|||
jmp reqL1L2 |
|||
|
|||
req_l1nl2m: |
|||
<%= global.toMont_a() %> |
|||
jmp reqL1L2 |
|||
|
|||
req_l1ml2: |
|||
bt r9, 62 ; check if montgomery second |
|||
jc req_l1ml2m |
|||
req_l1ml2n: |
|||
<%= global.toMont_b() %> |
|||
jmp reqL1L2 |
|||
|
|||
req_l1ml2m: |
|||
jmp reqL1L2 |
|||
|
|||
|
|||
;;;;;; |
|||
; eqL1L2 |
|||
;;;;;; |
|||
|
|||
reqL1L2: |
|||
<% for (let i=0; i<n64; i++) { %> |
|||
mov rax, [rsi + <%= 8+(i*8) %>] |
|||
cmp [rdx + <%= 8+(i*8) %>], rax |
|||
jne req_ret0 ; rsi<rdi => 1st > 2nd |
|||
<% } %> |
|||
|
|||
req_ret1: |
|||
mov rax, 1 |
|||
ret |
|||
|
|||
req_ret0: |
|||
xor rax, rax |
|||
ret |
|||
|
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; gt |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_gt: |
|||
call <%=name%>_rgt |
|||
mov [rdi], rax |
|||
ret |
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; lt |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_lt: |
|||
call <%=name%>_rlt |
|||
mov [rdi], rax |
|||
ret |
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; eq |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_eq: |
|||
call <%=name%>_req |
|||
mov [rdi], rax |
|||
ret |
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; neq |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_neq: |
|||
call <%=name%>_req |
|||
xor rax, 1 |
|||
mov [rdi], rax |
|||
ret |
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; geq |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_geq: |
|||
call <%=name%>_rlt |
|||
xor rax, 1 |
|||
mov [rdi], rax |
|||
ret |
|||
|
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; leq |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
; Compares two elements of any kind |
|||
; Params: |
|||
; rsi <= Pointer to element 1 |
|||
; rdx <= Pointer to element 2 |
|||
; rdi <= Pointer to result can be zero or one. |
|||
; Modified Registers: |
|||
; rax, rcx |
|||
;;;;;;;;;;;;;;;;;;;;;; |
|||
<%=name%>_leq: |
|||
call <%=name%>_rgt |
|||
xor rax, 1 |
|||
mov [rdi], rax |
|||
ret |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>English</string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>com.apple.xcode.dsym.tester</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>dSYM</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,748 @@ |
|||
const errs = require("./errs"); |
|||
|
|||
|
|||
const buildWasmFf = require("fflib").buildWasmFf; |
|||
|
|||
|
|||
module.exports = function buildRuntime(module, builder) { |
|||
|
|||
function buildInit() { |
|||
const f = module.addFunction("init"); |
|||
f.addLocal("i", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
// Set the stack to current memory
|
|||
f.addCode( |
|||
c.i32_store( |
|||
c.i32_const(4), |
|||
c.i32_shl( |
|||
c.i32_and( |
|||
c.current_memory(), |
|||
c.i32_const(0xFFFFFFF8) |
|||
), |
|||
c.i32_const(16) |
|||
) |
|||
) |
|||
); |
|||
|
|||
f.addCode( |
|||
// i=0
|
|||
c.setLocal("i", c.i32_const(0)), |
|||
c.block(c.loop( |
|||
// if (i==NComponents) break
|
|||
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NComponents))), |
|||
|
|||
// inputSignalsToTrigger[i] = components[i].nInputSignals
|
|||
c.i32_store( |
|||
c.i32_add( |
|||
c.i32_const(builder.pInputSignalsToTrigger), |
|||
c.i32_mul( |
|||
c.getLocal("i"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_load(c.i32_const(builder.ppComponents)), |
|||
c.i32_mul( |
|||
c.getLocal("i"), |
|||
c.i32_const(builder.sizeofComponent) // Sizeof component
|
|||
) |
|||
), |
|||
builder.offsetComponentNInputSignals |
|||
) |
|||
), |
|||
|
|||
// i=i+1
|
|||
c.setLocal( |
|||
"i", |
|||
c.i32_add( |
|||
c.getLocal("i"), |
|||
c.i32_const(1) |
|||
) |
|||
), |
|||
c.br(0) |
|||
)) |
|||
); |
|||
|
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
// i=0
|
|||
c.setLocal("i", c.i32_const(0)), |
|||
c.block(c.loop( |
|||
// if (i==NSignals) break
|
|||
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NSignals))), |
|||
|
|||
// signalsAssigned[i] = false
|
|||
c.i32_store( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_mul( |
|||
c.getLocal("i"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
c.i32_const(0) |
|||
), |
|||
|
|||
// i=i+1
|
|||
c.setLocal( |
|||
"i", |
|||
c.i32_add( |
|||
c.getLocal("i"), |
|||
c.i32_const(1) |
|||
) |
|||
), |
|||
c.br(0) |
|||
)) |
|||
); |
|||
} |
|||
|
|||
f.addCode( |
|||
c.call( |
|||
"Fr_copy", |
|||
c.i32_const(builder.pSignals), |
|||
c.i32_add( |
|||
c.i32_load(c.i32_const(builder.ppConstants)), |
|||
c.i32_const(builder.addConstant(1) * builder.sizeFr) |
|||
) |
|||
) |
|||
); |
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
c.i32_store( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_const(1) |
|||
) |
|||
); |
|||
} |
|||
|
|||
f.addCode( |
|||
// i=0
|
|||
c.setLocal("i", c.i32_const(0)), |
|||
c.block(c.loop( |
|||
// if (i==NComponents) break
|
|||
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NComponents))), |
|||
|
|||
// if (inputSignalsToTrigger[i] == 0) triggerComponent(i)
|
|||
c.if( |
|||
c.i32_eqz( |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_const(builder.pInputSignalsToTrigger), |
|||
c.i32_mul( |
|||
c.getLocal("i"), |
|||
c.i32_const(4) |
|||
) |
|||
) |
|||
) |
|||
), |
|||
c.call( |
|||
"triggerComponent", |
|||
c.getLocal("i") |
|||
) |
|||
), |
|||
|
|||
// i=i+1
|
|||
c.setLocal( |
|||
"i", |
|||
c.i32_add( |
|||
c.getLocal("i"), |
|||
c.i32_const(1) |
|||
) |
|||
), |
|||
c.br(0) |
|||
)) |
|||
); |
|||
|
|||
} |
|||
|
|||
|
|||
function buildTriggerComponent() { |
|||
const f = module.addFunction("triggerComponent"); |
|||
f.addParam("component", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.call_indirect( |
|||
c.getLocal("component"), // Idx in table
|
|||
c.getLocal("component") // Parameter
|
|||
) |
|||
); |
|||
|
|||
} |
|||
|
|||
|
|||
function buildHash2ComponentEntry() { |
|||
const f = module.addFunction("hash2ComponentEntry"); |
|||
f.addParam("component", "i32"); |
|||
f.addParam("hash", "i64"); |
|||
f.setReturnType("i32"); |
|||
|
|||
f.addLocal("pComponent", "i32"); |
|||
f.addLocal("pHashTable", "i32"); |
|||
f.addLocal("hIdx", "i32"); |
|||
f.addLocal("h", "i64"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.setLocal( |
|||
"pComponent", |
|||
c.i32_add( |
|||
c.i32_load(c.i32_const(builder.ppComponents)), // pComponents
|
|||
c.i32_mul( |
|||
c.getLocal("component"), |
|||
c.i32_const(20) // sizeof(Component)
|
|||
) |
|||
) |
|||
), |
|||
c.setLocal( |
|||
"pHashTable", |
|||
c.i32_load(c.getLocal("pComponent")) |
|||
), |
|||
c.setLocal( |
|||
"hIdx", |
|||
c.i32_and( |
|||
c.i32_wrap_i64(c.getLocal("hash")), |
|||
c.i32_const(0xFF) |
|||
) |
|||
), |
|||
c.block(c.loop( |
|||
c.setLocal( |
|||
"h", |
|||
c.i64_load( |
|||
c.i32_add( |
|||
c.getLocal("pHashTable"), |
|||
c.i32_mul( |
|||
c.getLocal("hIdx"), |
|||
c.i32_const(12) |
|||
) |
|||
) |
|||
) |
|||
), |
|||
c.br_if(1, c.i64_eq(c.getLocal("h"), c.getLocal("hash"))), |
|||
c.if( |
|||
c.i64_eqz(c.getLocal("h")), |
|||
c.call( |
|||
"err", |
|||
c.i32_const(errs.HASH_NOT_FOUND.code), |
|||
c.i32_const(errs.HASH_NOT_FOUND.pointer) |
|||
) |
|||
), |
|||
c.setLocal( |
|||
"hIdx", |
|||
c.i32_and( |
|||
c.i32_add( |
|||
c.getLocal("hIdx"), |
|||
c.i32_const(1) |
|||
), |
|||
c.i32_const(0xFF) |
|||
) |
|||
), |
|||
c.br(0) |
|||
)), |
|||
|
|||
c.i32_add( // pComponentEntry
|
|||
c.i32_load( // pComponentEntryTable
|
|||
c.i32_add( |
|||
c.getLocal("pComponent"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
c.i32_mul( |
|||
c.i32_load( // idx to the componentEntry
|
|||
c.i32_add( |
|||
c.getLocal("pHashTable"), |
|||
c.i32_mul( |
|||
c.getLocal("hIdx"), |
|||
c.i32_const(12) |
|||
) |
|||
), |
|||
8 |
|||
), |
|||
c.i32_const(12) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
function buildGetFromComponentEntry(fnName, offset, type) { |
|||
const f = module.addFunction(fnName); |
|||
f.addParam("pR", "i32"); |
|||
f.addParam("component", "i32"); |
|||
f.addParam("hash", "i64"); |
|||
f.addLocal("pComponentEntry", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.setLocal( |
|||
"pComponentEntry", |
|||
c.call( |
|||
"hash2ComponentEntry", |
|||
c.getLocal("component"), |
|||
c.getLocal("hash") |
|||
) |
|||
), |
|||
c.if( // If type is not signal
|
|||
c.i32_ne( |
|||
c.i32_load( |
|||
c.getLocal("pComponentEntry"), |
|||
8 // type offset
|
|||
), |
|||
c.i32_const(type) |
|||
), |
|||
c.call( |
|||
"err", |
|||
c.i32_const(errs.INVALID_TYPE.code), |
|||
c.i32_const(errs.INVALID_TYPE.pointer) |
|||
) |
|||
), |
|||
c.i32_store( |
|||
c.getLocal("pR"), |
|||
c.i32_load( |
|||
c.getLocal("pComponentEntry"), |
|||
offset |
|||
) |
|||
) |
|||
); |
|||
|
|||
const f2 = module.addFunction(fnName + "32"); |
|||
f2.addParam("pR", "i32"); |
|||
f2.addParam("component", "i32"); |
|||
f2.addParam("hashMSB", "i32"); |
|||
f2.addParam("hashLSB", "i32"); |
|||
|
|||
const c2 = f2.getCodeBuilder(); |
|||
|
|||
f2.addCode( |
|||
c2.call( |
|||
fnName, |
|||
c2.getLocal("pR"), |
|||
c2.getLocal("component"), |
|||
c2.i64_or( |
|||
c2.i64_shl( |
|||
c2.i64_extend_i32_u(c2.getLocal("hashMSB")), |
|||
c2.i64_const(32) |
|||
), |
|||
c2.i64_extend_i32_u(c2.getLocal("hashLSB")) |
|||
) |
|||
) |
|||
); |
|||
|
|||
} |
|||
|
|||
|
|||
function buildGetSignal() { |
|||
const f = module.addFunction("getSignal"); |
|||
f.addParam("cIdx", "i32"); |
|||
f.addParam("pR", "i32"); |
|||
f.addParam("component", "i32"); |
|||
f.addParam("signal", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
c.if( |
|||
c.i32_eqz( |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
) |
|||
), |
|||
c.call( |
|||
"err", |
|||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code), |
|||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
f.addCode( |
|||
c.call( |
|||
"Fr_copy", |
|||
c.getLocal("pR"), |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignals), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(builder.sizeFr) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
|
|||
function buildSetSignal() { |
|||
const f = module.addFunction("setSignal"); |
|||
f.addParam("cIdx", "i32"); |
|||
f.addParam("component", "i32"); |
|||
f.addParam("signal", "i32"); |
|||
f.addParam("pVal", "i32"); |
|||
f.addLocal("signalsToTrigger", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
|
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
c.if( |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
), |
|||
c.call( |
|||
"err", |
|||
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.code), |
|||
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.pointer) |
|||
) |
|||
), |
|||
c.i32_store( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
c.i32_const(1) |
|||
), |
|||
); |
|||
} |
|||
|
|||
f.addCode( |
|||
c.call( |
|||
"Fr_copy", |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignals), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(builder.sizeFr) |
|||
) |
|||
), |
|||
c.getLocal("pVal"), |
|||
) |
|||
); |
|||
|
|||
f.addCode( |
|||
c.if( // If ( mapIsInput[s >> 5] & 1 << (s & 0x1f) )
|
|||
c.i32_and( |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_load(c.i32_const(builder.ppMapIsInput)), |
|||
c.i32_shl( |
|||
c.i32_shr_u( |
|||
c.getLocal("signal"), |
|||
c.i32_const(5) |
|||
), |
|||
c.i32_const(2) |
|||
) |
|||
) |
|||
), |
|||
c.i32_shl( |
|||
c.i32_const(1), |
|||
c.i32_and( |
|||
c.getLocal("signal"), |
|||
c.i32_const(0x1F) |
|||
) |
|||
) |
|||
), |
|||
[ |
|||
|
|||
...c.setLocal( |
|||
"signalsToTrigger", |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_const(builder.pInputSignalsToTrigger), |
|||
c.i32_mul( |
|||
c.getLocal("component"), |
|||
c.i32_const(4) |
|||
) |
|||
) |
|||
) |
|||
), |
|||
|
|||
...c.if( // if (signalsToTrigger > 0)
|
|||
c.i32_gt_u( |
|||
c.getLocal("signalsToTrigger"), |
|||
c.i32_const(0) |
|||
), |
|||
[ |
|||
...c.setLocal( // signalsToTrigger--
|
|||
"signalsToTrigger", |
|||
c.i32_sub( |
|||
c.getLocal("signalsToTrigger"), |
|||
c.i32_const(1) |
|||
) |
|||
), |
|||
...c.i32_store( |
|||
c.i32_add( |
|||
c.i32_const(builder.pInputSignalsToTrigger), |
|||
c.i32_mul( |
|||
c.getLocal("component"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
c.getLocal("signalsToTrigger"), |
|||
), |
|||
...c.if( // if (signalsToTrigger==0) triggerCompomnent(component)
|
|||
c.i32_eqz(c.getLocal("signalsToTrigger")), |
|||
c.call( |
|||
"triggerComponent", |
|||
c.getLocal("component") |
|||
) |
|||
) |
|||
], |
|||
c.call( |
|||
"err2", |
|||
c.i32_const(errs.MAPISINPUT_DONT_MATCH.code), |
|||
c.i32_const(errs.MAPISINPUT_DONT_MATCH.pointer), |
|||
c.getLocal("component"), |
|||
c.getLocal("signal") |
|||
) |
|||
) |
|||
] |
|||
) |
|||
); |
|||
} |
|||
|
|||
function buildComponentFinished() { |
|||
const f = module.addFunction("componentFinished"); |
|||
f.addParam("cIdx", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode(c.ret([])); |
|||
} |
|||
|
|||
function buildCheckConstraint() { |
|||
const pTmp = module.alloc(builder.sizeFr); |
|||
const f = module.addFunction("checkConstraint"); |
|||
f.addParam("cIdx", "i32"); |
|||
f.addParam("pA", "i32"); |
|||
f.addParam("pB", "i32"); |
|||
f.addParam("pStr", "i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
c.call( |
|||
"Fr_eq", |
|||
c.getLocal(c.i32_const(pTmp)), |
|||
c.getLocal("pA"), |
|||
c.getLocal("pB") |
|||
), |
|||
c.if ( |
|||
c.eqz( |
|||
c.call( |
|||
"Fr_isTrue", |
|||
c.getLocal(c.i32_const(pTmp)), |
|||
) |
|||
), |
|||
c.call( |
|||
"err4", |
|||
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.code), |
|||
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.pointer), |
|||
c.getLocal("cIdx"), |
|||
c.getLocal("pA"), |
|||
c.getLocal("pB"), |
|||
c.getLocal("pStr"), |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
function buildGetNVars() { |
|||
const f = module.addFunction("getNVars"); |
|||
f.setReturnType("i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode(c.i32_const(builder.header.NVars)); |
|||
} |
|||
|
|||
function buildGetFrLen() { |
|||
const f = module.addFunction("getFrLen"); |
|||
f.setReturnType("i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.i32_const(builder.sizeFr)); |
|||
} |
|||
|
|||
function buildGetPRawPrime() { |
|||
const f = module.addFunction("getPRawPrime"); |
|||
f.setReturnType("i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.i32_const(module.modules["Fr_F1m"].pq)); |
|||
} |
|||
|
|||
function buildGetPWitness() { |
|||
const f = module.addFunction("getPWitness"); |
|||
f.addParam("w", "i32"); |
|||
f.addLocal("signal", "i32"); |
|||
f.setReturnType("i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
|
|||
f.addCode( |
|||
c.setLocal( |
|||
"signal", |
|||
c.i32_load( // wit2sig[w]
|
|||
c.i32_add( |
|||
c.i32_load( c.i32_const(builder.ppWit2sig)), |
|||
c.i32_mul( |
|||
c.getLocal("w"), |
|||
c.i32_const(4) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
|
|||
if (builder.sanityCheck) { |
|||
f.addCode( |
|||
c.if( |
|||
c.i32_eqz( |
|||
c.i32_load( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignalsAssigned), |
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(4) |
|||
) |
|||
), |
|||
) |
|||
), |
|||
c.call( |
|||
"err", |
|||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code), |
|||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
f.addCode( |
|||
c.i32_add( |
|||
c.i32_const(builder.pSignals), |
|||
|
|||
c.i32_mul( |
|||
c.getLocal("signal"), |
|||
c.i32_const(builder.sizeFr) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
function buildFrToInt() { |
|||
const f = module.addFunction("Fr_toInt"); |
|||
f.addParam("p", "i32"); |
|||
f.setReturnType("i32"); |
|||
|
|||
const c = f.getCodeBuilder(); |
|||
|
|||
f.addCode( |
|||
c.i32_load(c.getLocal("p")) |
|||
); |
|||
|
|||
// TODO Handle long and montgomery.
|
|||
} |
|||
|
|||
|
|||
const fErr = module.addIimportFunction("err", "runtime"); |
|||
fErr.addParam("code", "i32"); |
|||
fErr.addParam("pStr", "i32"); |
|||
|
|||
const fErr1 = module.addIimportFunction("err1", "runtime"); |
|||
fErr1.addParam("code", "i32"); |
|||
fErr1.addParam("pStr", "i32"); |
|||
fErr1.addParam("param1", "i32"); |
|||
|
|||
const fErr2 = module.addIimportFunction("err2", "runtime"); |
|||
fErr2.addParam("code", "i32"); |
|||
fErr2.addParam("pStr", "i32"); |
|||
fErr2.addParam("param1", "i32"); |
|||
fErr2.addParam("param2", "i32"); |
|||
|
|||
const fErr3 = module.addIimportFunction("err3", "runtime"); |
|||
fErr3.addParam("code", "i32"); |
|||
fErr3.addParam("pStr", "i32"); |
|||
fErr3.addParam("param1", "i32"); |
|||
fErr3.addParam("param2", "i32"); |
|||
fErr3.addParam("param3", "i32"); |
|||
|
|||
const fErr4 = module.addIimportFunction("err4", "runtime"); |
|||
fErr4.addParam("code", "i32"); |
|||
fErr4.addParam("pStr", "i32"); |
|||
fErr4.addParam("param1", "i32"); |
|||
fErr4.addParam("param2", "i32"); |
|||
fErr4.addParam("param3", "i32"); |
|||
fErr4.addParam("param4", "i32"); |
|||
|
|||
buildWasmFf(module, "Fr", builder.header.P); |
|||
|
|||
builder.pSignals=module.alloc(builder.header.NSignals*builder.sizeFr); |
|||
builder.pInputSignalsToTrigger=module.alloc(builder.header.NComponents*4); |
|||
if (builder.sanityCheck) { |
|||
builder.pSignalsAssigned=module.alloc(builder.header.NSignals*4); |
|||
} |
|||
|
|||
buildHash2ComponentEntry(); |
|||
|
|||
buildTriggerComponent(); |
|||
buildInit(); |
|||
|
|||
buildGetFromComponentEntry("getSubComponentOffset", 0 /* offset */, builder.TYPE_COMPONENT); |
|||
buildGetFromComponentEntry("getSubComponentSizes", 4 /* offset */, builder.TYPE_COMPONENT); |
|||
|
|||
buildGetFromComponentEntry("getSignalOffset", 0 /* offset */, builder.TYPE_SIGNAL); |
|||
buildGetFromComponentEntry("getSignalSizes", 4 /* offset */, builder.TYPE_SIGNAL); |
|||
|
|||
buildGetSignal(); |
|||
buildSetSignal(); |
|||
|
|||
buildComponentFinished(); |
|||
|
|||
buildCheckConstraint(); |
|||
|
|||
buildGetNVars(); |
|||
buildGetFrLen(); |
|||
buildGetPWitness(); |
|||
buildGetPRawPrime(); |
|||
|
|||
buildFrToInt(); |
|||
|
|||
module.exportFunction("init"); |
|||
module.exportFunction("getNVars"); |
|||
module.exportFunction("getFrLen"); |
|||
module.exportFunction("getSignalOffset32"); |
|||
module.exportFunction("setSignal"); |
|||
module.exportFunction("getPWitness"); |
|||
module.exportFunction("Fr_toInt"); |
|||
module.exportFunction("getPRawPrime"); |
|||
|
|||
}; |
@ -0,0 +1,10 @@ |
|||
module.exports = { |
|||
STACK_OUT_OF_MEM: {code: 1, str: "Stack out of memory"}, |
|||
STACK_TOO_SMALL: {code: 2, str: "Stack too small"}, |
|||
HASH_NOT_FOUND: {code: 3, str: "Hash not found"}, |
|||
INVALID_TYPE: {code: 4, str: "Invalid type"}, |
|||
ACCESSING_NOT_ASSIGNED_SIGNAL: {code: 5, str: "Accessing a not assigned signal"}, |
|||
SIGNAL_ASSIGNED_TWICE: {code: 6, str: "Signal assigned twice"}, |
|||
CONSTRAIN_DOES_NOT_MATCH: {code: 7, str: "Constraint doesn't match"}, |
|||
MAPISINPUT_DONT_MATCH: {code: 8, str: "MapIsInput don't match"}, |
|||
}; |
@ -0,0 +1,167 @@ |
|||
const chai = require("chai"); |
|||
const assert = chai.assert; |
|||
|
|||
const fs = require("fs"); |
|||
var tmp = require("tmp-promise"); |
|||
const path = require("path"); |
|||
const compiler = require("../../src/compiler"); |
|||
const util = require("util"); |
|||
const exec = util.promisify(require("child_process").exec); |
|||
|
|||
const stringifyBigInts = require("../../src/utils").stringifyBigInts; |
|||
const unstringifyBigInts = require("../../src/utils").unstringifyBigInts; |
|||
const bigInt = require("big-integer"); |
|||
const utils = require("../../src/utils"); |
|||
const loadR1cs = require("../../src/r1csfile").loadR1cs; |
|||
const ZqField = require("fflib").ZqField; |
|||
|
|||
const WitnessCalculator = require("./witness_calculator"); |
|||
|
|||
module.exports = wasm_tester; |
|||
|
|||
|
|||
async function wasm_tester(circomFile, _options) { |
|||
tmp.setGracefulCleanup(); |
|||
|
|||
const dir = await tmp.dir({prefix: "circom_", unsafeCleanup: true }); |
|||
|
|||
// console.log(dir.path);
|
|||
|
|||
const baseName = path.basename(circomFile, ".circom"); |
|||
const options = Object.assign({}, _options); |
|||
|
|||
options.wasmWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".wasm")); |
|||
options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym")); |
|||
options.r1csFileName = path.join(dir.path, baseName + ".r1cs"); |
|||
|
|||
const promisesArr = []; |
|||
promisesArr.push(new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill))); |
|||
|
|||
await compiler(circomFile, options); |
|||
|
|||
await Promise.all(promisesArr); |
|||
|
|||
const wc = await WitnessCalculator.fromFile(path.join(dir.path, baseName + ".wasm")); |
|||
|
|||
return new WasmTester(dir, baseName, wc); |
|||
} |
|||
|
|||
class WasmTester { |
|||
|
|||
constructor(dir, baseName, witnessCalculator) { |
|||
this.dir=dir; |
|||
this.baseName = baseName; |
|||
this.witnessCalculator = witnessCalculator; |
|||
} |
|||
|
|||
async release() { |
|||
await this.dir.cleanup(); |
|||
} |
|||
|
|||
async calculateWitness(input) { |
|||
|
|||
return await this.witnessCalculator.calculateWitness(input); |
|||
} |
|||
|
|||
async loadSymbols() { |
|||
if (this.symbols) return; |
|||
this.symbols = {}; |
|||
const symsStr = await fs.promises.readFile( |
|||
path.join(this.dir.path, this.baseName + ".sym"), |
|||
"utf8" |
|||
); |
|||
const lines = symsStr.split("\n"); |
|||
for (let i=0; i<lines.length; i++) { |
|||
const arr = lines[i].split(","); |
|||
if (arr.length!=3) continue; |
|||
this.symbols[arr[2]] = { |
|||
idx: Number(arr[0]), |
|||
idxWit: Number(arr[1]) |
|||
}; |
|||
} |
|||
} |
|||
|
|||
async loadConstraints() { |
|||
const self = this; |
|||
if (this.constraints) return; |
|||
const r1cs = await loadR1cs(path.join(this.dir.path, this.baseName + ".r1cs"),true, false); |
|||
self.field = new ZqField(r1cs.prime); |
|||
self.nWires = r1cs.nWires; |
|||
self.constraints = r1cs.constraints; |
|||
} |
|||
|
|||
async assertOut(actualOut, expectedOut) { |
|||
const self = this; |
|||
if (!self.symbols) await self.loadSymbols(); |
|||
|
|||
checkObject("main", expectedOut); |
|||
|
|||
function checkObject(prefix, eOut) { |
|||
|
|||
if (Array.isArray(eOut)) { |
|||
for (let i=0; i<eOut.length; i++) { |
|||
checkObject(prefix + "["+i+"]", eOut[i]); |
|||
} |
|||
} else if ((typeof eOut == "object")&&(eOut.constructor.name == "Object")) { |
|||
for (let k in eOut) { |
|||
checkObject(prefix + "."+k, eOut[k]); |
|||
} |
|||
} else { |
|||
if (typeof self.symbols[prefix] == "undefined") { |
|||
assert(false, "Output variable not defined: "+ prefix); |
|||
} |
|||
const ba = bigInt(actualOut[self.symbols[prefix].idxWit]).toString(); |
|||
const be = bigInt(eOut).toString(); |
|||
assert.strictEqual(ba, be, prefix); |
|||
} |
|||
} |
|||
} |
|||
|
|||
async getDecoratedOutput(witness) { |
|||
const self = this; |
|||
const lines = []; |
|||
if (!self.symbols) await self.loadSymbols(); |
|||
for (let n in self.symbols) { |
|||
let v; |
|||
if (utils.isDefined(witness[self.symbols[n].idxWit])) { |
|||
v = witness[self.symbols[n].idxWit].toString(); |
|||
} else { |
|||
v = "undefined"; |
|||
} |
|||
lines.push(`${n} --> ${v}`); |
|||
} |
|||
return lines.join("\n"); |
|||
} |
|||
|
|||
async checkConstraints(witness) { |
|||
const self = this; |
|||
if (!self.constraints) await self.loadConstraints(); |
|||
for (let i=0; i<self.constraints.length; i++) { |
|||
checkConstraint(self.constraints[i]); |
|||
} |
|||
|
|||
function checkConstraint(constraint) { |
|||
const F = self.field; |
|||
const a = evalLC(constraint.a); |
|||
const b = evalLC(constraint.b); |
|||
const c = evalLC(constraint.c); |
|||
|
|||
assert (F.sub(F.mul(a,b), c).isZero(), "Constraint doesn't match"); |
|||
} |
|||
|
|||
function evalLC(lc) { |
|||
const F = self.field; |
|||
let v = F.zero; |
|||
for (let w in lc) { |
|||
v = F.add( |
|||
v, |
|||
F.mul( lc[w], witness[w] ) |
|||
); |
|||
} |
|||
return v; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
|
@ -0,0 +1,186 @@ |
|||
/* globals WebAssembly */ |
|||
|
|||
const fs = require("fs"); |
|||
const utils = require("../../src/utils"); |
|||
const bigInt = require("big-integer"); |
|||
|
|||
module.exports.fromFile = async function(file) { |
|||
|
|||
|
|||
const code = await fs.promises.readFile(file); |
|||
|
|||
return await module.exports.fromBuffer(code); |
|||
}; |
|||
|
|||
module.exports.fromBuffer = async function(code) { |
|||
|
|||
const memory = new WebAssembly.Memory({initial:20000}); |
|||
const wasmModule = await WebAssembly.compile(code); |
|||
|
|||
const instance = await WebAssembly.instantiate(wasmModule, { |
|||
env: { |
|||
"memory": memory |
|||
}, |
|||
runtime: { |
|||
err: function(code, pstr) { |
|||
console.log("ERROR", code, p2str(pstr)); |
|||
}, |
|||
err1: function(code, pstr, a) { |
|||
console.log("ERROR: ", code, p2str(pstr), a); |
|||
}, |
|||
err2: function(code, pstr, a, b) { |
|||
console.log("ERROR: ", code, p2str(pstr), a, b); |
|||
}, |
|||
err3: function(code, pstr, a, b, c) { |
|||
console.log("ERROR: ", code, p2str(pstr), a, b, c); |
|||
}, |
|||
err4: function(code, pstr, a,b,c,d) { |
|||
console.log("ERROR: ", code, p2str(pstr), a, b, c, d); |
|||
}, |
|||
} |
|||
}); |
|||
|
|||
return new WitnessCalculator(memory, instance); |
|||
|
|||
function p2str(p) { |
|||
return "TODO"+p; |
|||
} |
|||
}; |
|||
|
|||
class WitnessCalculator { |
|||
constructor(memory, instance) { |
|||
this.memory = memory; |
|||
this.i32 = new Uint32Array(memory.buffer); |
|||
this.instance = instance; |
|||
|
|||
this.n32 = (this.instance.exports.getFrLen() >> 2) - 2; |
|||
const pRawPrime = this.instance.exports.getPRawPrime(); |
|||
|
|||
this.prime = bigInt(0); |
|||
for (let i=this.n32-1; i>=0; i--) { |
|||
this.prime = this.prime.shiftLeft(32); |
|||
this.prime = this.prime.add(bigInt(this.i32[(pRawPrime >> 2) + i])); |
|||
} |
|||
|
|||
this.mask32 = bigInt("FFFFFFFF", 16); |
|||
this.NVars = this.instance.exports.getNVars(); |
|||
this.n64 = Math.floor((this.prime.bitLength() - 1) / 64)+1; |
|||
this.R = bigInt.one.shiftLeft(this.n64*64); |
|||
this.RInv = this.R.modInv(this.prime); |
|||
|
|||
} |
|||
|
|||
async calculateWitness(input) { |
|||
const w = []; |
|||
const old0 = this.i32[0]; |
|||
this.instance.exports.init(); |
|||
const pSigOffset = this.allocInt(); |
|||
const pFr = this.allocFr(); |
|||
for (let k in input) { |
|||
const h = utils.fnvHash(k); |
|||
const hMSB = parseInt(h.slice(0,8), 16); |
|||
const hLSB = parseInt(h.slice(8,16), 16); |
|||
this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB); |
|||
const sigOffset = this.getInt(pSigOffset); |
|||
const fArr = utils.flatArray(input[k]); |
|||
for (let i=0; i<fArr.length; i++) { |
|||
this.setFr(pFr, fArr[i]); |
|||
this.instance.exports.setSignal(0, 0, sigOffset + i, pFr); |
|||
} |
|||
} |
|||
|
|||
|
|||
for (let i=0; i<this.NVars; i++) { |
|||
const pWitness = this.instance.exports.getPWitness(i); |
|||
w.push(this.getFr(pWitness)); |
|||
} |
|||
|
|||
this.i32[0] = old0; |
|||
return w; |
|||
} |
|||
|
|||
allocInt() { |
|||
const p = this.i32[0]; |
|||
this.i32[0] = p+8; |
|||
return p; |
|||
} |
|||
|
|||
allocFr() { |
|||
const p = this.i32[0]; |
|||
this.i32[0] = p+this.n32*4 + 8; |
|||
return p; |
|||
} |
|||
|
|||
getInt(p) { |
|||
return this.i32[p>>2]; |
|||
} |
|||
|
|||
setInt(p, v) { |
|||
this.i32[p>>2] = v; |
|||
} |
|||
|
|||
getFr(p) { |
|||
const idx = (p>>2); |
|||
|
|||
if (this.i32[idx + 1] & 0x80000000) { |
|||
let res= bigInt(0); |
|||
for (let i=this.n32-1; i>=0; i--) { |
|||
res = res.shiftLeft(32); |
|||
res = res.add(bigInt(this.i32[idx+2+i])); |
|||
} |
|||
if (this.i32[idx + 1] & 0x40000000) { |
|||
return fromMontgomery(res); |
|||
} else { |
|||
return res; |
|||
} |
|||
|
|||
} else { |
|||
if (this.i32[idx] & 0x80000000) { |
|||
return this.prime.add( bigInt(this.i32[idx]).minus(bigInt(0x100000000)) ); |
|||
} else { |
|||
return bigInt(this.i32[idx]); |
|||
} |
|||
} |
|||
|
|||
function fromMontgomery(n) { |
|||
return n.times(this.RInv).mod(this.prime); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
setFr(p, v) { |
|||
const self = this; |
|||
v = bigInt(v); |
|||
|
|||
if (v.lt(bigInt("80000000", 16)) ) { |
|||
return setShortPositive(v); |
|||
} |
|||
if (v.geq(self.prime.minus(bigInt("80000000", 16))) ) { |
|||
return setShortNegative(v); |
|||
} |
|||
return setLongNormal(v); |
|||
|
|||
function setShortPositive(a) { |
|||
self.i32[(p >> 2)] = parseInt(a); |
|||
self.i32[(p >> 2) + 1] = 0; |
|||
} |
|||
|
|||
function setShortNegative(a) { |
|||
const b = bigInt("80000000", 16 ).add(a.minus( self.prime.minus(bigInt("80000000", 16 )))); |
|||
self.i32[(p >> 2)] = parseInt(b); |
|||
self.i32[(p >> 2) + 1] = 0; |
|||
} |
|||
|
|||
function setLongNormal(a) { |
|||
self.i32[(p >> 2)] = 0; |
|||
self.i32[(p >> 2) + 1] = 0x80000000; |
|||
for (let i=0; i<self.n32; i++) { |
|||
self.i32[(p >> 2) + 2 + i] = a.shiftRight(i*32).and(self.mask32); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
@ -1,28 +0,0 @@ |
|||
class BuilderWasm { |
|||
constructor() { |
|||
|
|||
} |
|||
|
|||
setHeader(header) { |
|||
this.header=header; |
|||
} |
|||
|
|||
// ht is an array of 256 element that can be undefined or [Hash, Idx, KeyName] elements.
|
|||
addHashMap(name, ht) { |
|||
this.hashTables[name] = ht; |
|||
} |
|||
|
|||
addComponentEntriesTable(name, cet) { |
|||
this.componentEntriesTables[name] = cet; |
|||
} |
|||
|
|||
addSizes(name, accSizes) { |
|||
this.sizes[name] = accSizes; |
|||
} |
|||
|
|||
build() { |
|||
|
|||
} |
|||
} |
|||
|
|||
module.exports = BuilderWasm; |
@ -0,0 +1,156 @@ |
|||
const Readable = require("stream").Readable; |
|||
|
|||
module.exports = function buildSyms(ctx) { |
|||
const rs = Readable(); |
|||
|
|||
let it = new ComponentIt(ctx, 0, "main"); |
|||
|
|||
let counter = 0; |
|||
|
|||
rs._read = function() { |
|||
const actual = it.current(); |
|||
if (actual == null ) { |
|||
rs.push(null); |
|||
return; |
|||
} |
|||
|
|||
|
|||
let s=actual.offset; |
|||
while (ctx.signals[s].e >= 0) s = ctx.signals[s].e; |
|||
let wId = ctx.signals[s].id; |
|||
if (typeof(wId) == "undefined") wId=-1; |
|||
rs.push(`${actual.offset},${wId},${actual.name}\n`); |
|||
|
|||
it.next(); |
|||
counter ++; |
|||
if ((ctx.verbose)&&(counter%10000 == 0)) console.log("Symbols saved: "+counter); |
|||
}; |
|||
|
|||
return rs; |
|||
}; |
|||
|
|||
|
|||
|
|||
class SignalIt { |
|||
constructor (ctx, offset, prefix) { |
|||
this.ctx = ctx; |
|||
this.offset = offset; |
|||
this.prefix = prefix; |
|||
this.cur = 0; |
|||
} |
|||
|
|||
next() { |
|||
this.cur = 1; |
|||
|
|||
return this.current(); |
|||
} |
|||
|
|||
current() { |
|||
if (this.cur == 0) { |
|||
return {offset: this.offset, name: this.prefix}; |
|||
} |
|||
} |
|||
} |
|||
|
|||
class ArrayIt { |
|||
constructor (ctx, type, sizes, offset, prefix) { |
|||
if (sizes.length == 0) { |
|||
if (type == "S") { |
|||
return new SignalIt(ctx, offset, prefix); |
|||
} else { |
|||
return new ComponentIt(ctx, offset, prefix); |
|||
} |
|||
} |
|||
|
|||
this.ctx = ctx; |
|||
this.type = type; |
|||
this.sizes = sizes; |
|||
this.offset = offset; |
|||
this.prefix = prefix; |
|||
|
|||
|
|||
|
|||
this.subIt = null; |
|||
this.cur = 0; |
|||
|
|||
this.subArrSize = 1; |
|||
|
|||
for (let i=1; i<sizes.length; i++) { |
|||
this.subArrSize *= sizes[i]; |
|||
} |
|||
|
|||
this._loadSubIt(); |
|||
|
|||
|
|||
} |
|||
|
|||
_loadSubIt() { |
|||
if (this.cur < this.sizes[0]) { |
|||
this.subIt = new ArrayIt(this.ctx, this.type, this.sizes.slice(1), this.offset + this.cur*this.subArrSize, this.prefix + "[" + this.cur + "]"); |
|||
} |
|||
} |
|||
|
|||
next() { |
|||
if (this.subIt) { |
|||
const res = this.subIt.next(); |
|||
if (res == null) { |
|||
this.subIt = null; |
|||
this.cur++; |
|||
this._loadSubIt(); |
|||
} |
|||
} |
|||
|
|||
return this.current(); |
|||
|
|||
} |
|||
|
|||
current() { |
|||
if (this.subIt) { |
|||
return this.subIt.current(); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
class ComponentIt { |
|||
constructor (ctx, idxComponent, prefix) { |
|||
this.ctx = ctx; |
|||
this.idxComponent = idxComponent; |
|||
this.prefix = prefix; |
|||
this.names = Object.keys(ctx.components[idxComponent].names.o); |
|||
|
|||
this.subIt = null; |
|||
this.cur = 0; |
|||
this._loadSubIt(); |
|||
|
|||
} |
|||
|
|||
_loadSubIt() { |
|||
if (this.cur < this.names.length) { |
|||
const entrie = this.ctx.components[this.idxComponent].names.o[this.names[this.cur]]; |
|||
this.subIt = new ArrayIt(this.ctx, entrie.type, entrie.sizes, entrie.offset, this.prefix + "." + this.names[this.cur]); |
|||
} |
|||
} |
|||
|
|||
next() { |
|||
if (this.subIt) { |
|||
const res = this.subIt.next(); |
|||
if (res == null) { |
|||
this.subIt = null; |
|||
this.cur++; |
|||
this._loadSubIt(); |
|||
} |
|||
} |
|||
|
|||
return this.current(); |
|||
} |
|||
|
|||
current() { |
|||
if (this.subIt) { |
|||
return this.subIt.current(); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -1,52 +0,0 @@ |
|||
|
|||
const ModuleBuilder = require("wasmbuilder").ModuleBuilder; |
|||
const gen = require("./gencode"); |
|||
|
|||
|
|||
module.exports = function buildWasm(ctx) { |
|||
|
|||
const fDefined = {}; |
|||
|
|||
ctx.module = new ModuleBuilder(); |
|||
for (let f in ctx.functions) { |
|||
ctx.f = ctx.module.addFunction(f); |
|||
ctx.c = ctx.f.getCodeBuilder(); |
|||
|
|||
ctx.scope = {}; |
|||
for (let p in ctx.functions[f].params) { |
|||
const param = ctx.functions[f].params[p]; |
|||
ctx.f.addParam(param.name, "i32"); |
|||
ctx.scope[param.name] = { |
|||
type: "PARAM", |
|||
sels: param.sels, |
|||
getter: () => { return ctx.c.getLocal(param.name); }, |
|||
setter: (v) => { return ctx.c.setLocal(param.name, v); } |
|||
}; |
|||
} |
|||
|
|||
gen(ctx, ctx.functions[f].block); |
|||
} |
|||
|
|||
for (let i=0; i<ctx.components.length; i++) { |
|||
const h = hashComponentCall(ctx, i); |
|||
const fName = ctx.components[i].temlate+"_"+h; |
|||
if (!fDefined[fName]) { |
|||
|
|||
ctx.f = ctx.module.addFunction(fName); |
|||
ctx.c = ctx.f.getCodeBuilder(); |
|||
|
|||
ctx.scope = {}; |
|||
for (let p in ctx.components[i].params) { |
|||
ctx.scope[p] = createConstant(ctx, ctx.components[i].params[p]); |
|||
} |
|||
|
|||
gen(ctx, ctx.templates[ctx.components[i].temlate].block); |
|||
} |
|||
ctx.components[i].f = fName; |
|||
} |
|||
}; |
|||
|
|||
function buildSetSignal(ctx) { |
|||
|
|||
|
|||
} |
@ -0,0 +1,21 @@ |
|||
|
|||
const Readable = require("stream").Readable; |
|||
|
|||
module.exports = function streamFromArrayBin(a) { |
|||
const rs = Readable(); |
|||
|
|||
let curIndex = 0; |
|||
|
|||
rs._read = function(size) { |
|||
if (curIndex >= a.length) { |
|||
rs.push(null); |
|||
return; |
|||
} |
|||
const start = curIndex; |
|||
const end = Math.min(a.length, curIndex+size); |
|||
curIndex = end; |
|||
rs.push(a.slice(start, end)); |
|||
}; |
|||
|
|||
return rs; |
|||
}; |
@ -0,0 +1,343 @@ |
|||
const path = require("path"); |
|||
|
|||
const bigInt = require("big-integer"); |
|||
const c_tester = require("../index.js").c_tester; |
|||
|
|||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
|||
|
|||
|
|||
function normalize(o) { |
|||
if ((typeof(o) == "bigint") || o.isZero !== undefined) { |
|||
const res = bigInt(o); |
|||
return norm(res); |
|||
} else if (Array.isArray(o)) { |
|||
return o.map(normalize); |
|||
} else if (typeof o == "object") { |
|||
const res = {}; |
|||
for (let k in o) { |
|||
res[k] = normalize(o[k]); |
|||
} |
|||
return res; |
|||
} else { |
|||
const res = bigInt(o); |
|||
return norm(res); |
|||
} |
|||
|
|||
function norm(n) { |
|||
let res = n.mod(__P__); |
|||
if (res.isNegative()) res = __P__.add(res); |
|||
return res; |
|||
} |
|||
} |
|||
|
|||
|
|||
async function doTest(circuit, testVectors) { |
|||
const cir = await c_tester(path.join(__dirname, "circuits", circuit)); |
|||
|
|||
for (let i=0; i<testVectors.length; i++) { |
|||
const w = await cir.calculateWitness(normalize(testVectors[i][0])); |
|||
await cir.assertOut(w, normalize(testVectors[i][1]) ); |
|||
} |
|||
|
|||
await cir.release(); |
|||
} |
|||
|
|||
describe("basic cases", function () { |
|||
this.timeout(100000); |
|||
|
|||
it("inout", async () => { |
|||
await doTest( |
|||
"inout.circom", |
|||
[ |
|||
[{in1: 1, in2: [2,3], in3:[[4,5], [6,7], [8,9]]}, {out1: 1, out2: [2,3], out3: [[4,5], [6,7],[8,9]]}], |
|||
] |
|||
); |
|||
}); |
|||
it("add", async () => { |
|||
await doTest( |
|||
"add.circom", |
|||
[ |
|||
[{in: [0,0]}, {out: 0}], |
|||
[{in: [0,1]}, {out: 1}], |
|||
[{in: [1,2]}, {out: 3}], |
|||
[{in: [__P__.minus(1),1]}, {out: 0}], |
|||
] |
|||
); |
|||
}); |
|||
it("add constant", async () => { |
|||
await doTest( |
|||
"addconst1.circom", |
|||
[ |
|||
[{in: 0}, {out: 15}], |
|||
[{in: 10}, {out: 25}], |
|||
[{in: __P__.minus(2)}, {out: 13}], |
|||
] |
|||
); |
|||
}); |
|||
it("for unrolled", async () => { |
|||
await doTest( |
|||
"forunrolled.circom", |
|||
[ |
|||
[{in: 0}, {out: [0,1,2]}], |
|||
[{in: 10}, {out: [10, 11, 12]}], |
|||
[{in: __P__.minus(2)}, {out: [__P__.minus(2), __P__.minus(1), 0]}], |
|||
] |
|||
); |
|||
}); |
|||
it("for rolled", async () => { |
|||
await doTest( |
|||
"forrolled.circom", |
|||
[ |
|||
[{in: 0}, {out: 0}], |
|||
[{in: 10}, {out: 10}], |
|||
] |
|||
); |
|||
}); |
|||
it("while unrolled", async () => { |
|||
await doTest( |
|||
"whileunrolled.circom", |
|||
[ |
|||
[{in: 0}, {out: [0,1,2]}], |
|||
[{in: 10}, {out: [10, 11, 12]}], |
|||
[{in: __P__.minus(2)}, {out: [__P__.minus(2), __P__.minus(1), 0]}], |
|||
] |
|||
); |
|||
}); |
|||
it("while rolled", async () => { |
|||
await doTest( |
|||
"whilerolled.circom", |
|||
[ |
|||
[{in: 0}, {out: 0}], |
|||
[{in: 10}, {out: 10}], |
|||
] |
|||
); |
|||
}); |
|||
it("function1", async () => { |
|||
await doTest( |
|||
"function1.circom", |
|||
[ |
|||
[{in: 0}, {out: 3}], |
|||
[{in: 10}, {out: 13}], |
|||
[{in: __P__.minus(2)}, {out: 1}], |
|||
] |
|||
); |
|||
}); |
|||
it("function2", async () => { |
|||
await doTest( |
|||
"function2.circom", |
|||
[ |
|||
[{in: 0}, {out: 3}], |
|||
[{in: 10}, {out: 13}], |
|||
[{in: __P__.minus(2)}, {out: 1}], |
|||
] |
|||
); |
|||
}); |
|||
it("constants1", async () => { |
|||
await doTest( |
|||
"constants1.circom", |
|||
[ |
|||
[{in: 0}, {out: 42}], |
|||
[{in: 10}, {out: 52}], |
|||
[{in: __P__.minus(2)}, {out: 40}], |
|||
] |
|||
); |
|||
}); |
|||
it("arrays", async () => { |
|||
await doTest( |
|||
"arrays.circom", |
|||
[ |
|||
[{in: 0}, {out: [1, 8, 51]}], |
|||
[{in: 10}, {out: [11, 28, 111]}], |
|||
[{in: __P__.minus(2)}, {out: [__P__.minus(1), 4, 39]}], |
|||
] |
|||
); |
|||
}); |
|||
it("if unrolled", async () => { |
|||
await doTest( |
|||
"ifunrolled.circom", |
|||
[ |
|||
[{in: 0}, {out: [1, 3, 6]}], |
|||
[{in: 10}, {out: [11, 13, 16]}], |
|||
[{in: __P__.minus(2)}, {out: [__P__.minus(1), 1, 4]}], |
|||
] |
|||
); |
|||
}); |
|||
it("if rolled", async () => { |
|||
await doTest( |
|||
"ifrolled.circom", |
|||
[ |
|||
[{in: 0}, {out: [1, 0, 0]}], |
|||
[{in: 1}, {out: [0, 1, 0]}], |
|||
[{in: 2}, {out: [0, 0, 1]}], |
|||
[{in: 3}, {out: [0, 0, 0]}], |
|||
[{in: __P__.minus(2)}, {out: [0,0,0]}], |
|||
] |
|||
); |
|||
}); |
|||
it("inc", async () => { |
|||
await doTest( |
|||
"inc.circom", |
|||
[ |
|||
[{in: 0}, {out: [5, 2]}], |
|||
[{in: 1}, {out: [6, 4]}], |
|||
[{in: 2}, {out: [7, 6]}], |
|||
[{in: 3}, {out: [8, 8]}], |
|||
[{in: __P__.minus(2)}, {out: [3,__P__.minus(2)]}], |
|||
] |
|||
); |
|||
}); |
|||
it("dec", async () => { |
|||
await doTest( |
|||
"dec.circom", |
|||
[ |
|||
[{in: 0}, {out: [1, __P__.minus(2)]}], |
|||
[{in: 1}, {out: [2, 0]}], |
|||
[{in: 2}, {out: [3, 2]}], |
|||
[{in: 3}, {out: [4, 4]}], |
|||
[{in: __P__.minus(2)}, {out: [__P__.minus(1),__P__.minus(6)]}], |
|||
] |
|||
); |
|||
}); |
|||
it("ops", async () => { |
|||
await doTest( |
|||
"ops.circom", |
|||
[ |
|||
[{in: [-2, 2]}, {add: 0, sub: -4, mul: -4}], |
|||
[{in: [-1, 1]}, {add: 0, sub: -2, mul: -1}], |
|||
[{in: [ 0, 0]}, {add: 0, sub: 0, mul: 0}], |
|||
[{in: [ 1,-1]}, {add: 0, sub: 2, mul: -1}], |
|||
[{in: [ 2,-2]}, {add: 0, sub: 4, mul: -4}], |
|||
[{in: [-2,-3]}, {add: -5, sub: 1, mul: 6}], |
|||
[{in: [ 2, 3]}, {add: 5, sub: -1, mul: 6}], |
|||
] |
|||
); |
|||
}); |
|||
it("ops2", async () => { |
|||
await doTest( |
|||
"ops2.circom", |
|||
[ |
|||
[{in: [-2, 2]}, {div: -1, idiv: bigInt("10944121435919637611123202872628637544274182200208017171849102093287904247807"), mod: 1}], |
|||
[{in: [-1, 1]}, {div: -1, idiv: -1, mod: 0}], |
|||
[{in: [ 1,-1]}, {div: -1, idiv: 0, mod: 1}], |
|||
] |
|||
); |
|||
}); |
|||
it("ops3", async () => { |
|||
await doTest( |
|||
"ops3.circom", |
|||
[ |
|||
[{in: [-2, 2]}, {neg1: 2,neg2: -2, pow: 4}], |
|||
[{in: [0, 1]}, {neg1: 0, neg2: -1, pow: 0}], |
|||
[{in: [ 1,-1]}, {neg1: -1, neg2: 1, pow: 1}], |
|||
] |
|||
); |
|||
}); |
|||
it("Comparation ops", async () => { |
|||
await doTest( |
|||
"opscmp.circom", |
|||
[ |
|||
[{in: [ 8, 9]}, {lt: 1, leq: 1, eq:0, neq:1, geq: 0, gt:0}], |
|||
[{in: [-2,-2]}, {lt: 0, leq: 1, eq:1, neq:0, geq: 1, gt:0}], |
|||
[{in: [-1,-2]}, {lt: 0, leq: 0, eq:0, neq:1, geq: 1, gt:1}], |
|||
[{in: [ 1,-1]}, {lt: 0, leq: 0, eq:0, neq:1, geq: 1, gt:1}], // In mod, negative values are higher than positive. |
|||
] |
|||
); |
|||
}); |
|||
it("Bit ops", async () => { |
|||
const mask = bigInt("14474011154664524427946373126085988481658748083205070504932198000989141204991"); |
|||
const m1m = bigInt("7414231717174750794300032619171286606889616317210963838766006185586667290624"); |
|||
await doTest( |
|||
"opsbit.circom", |
|||
[ |
|||
[{in: [ 5, 3]}, {and: 1, or: 7, xor:6, not1:mask.minus(5), shl: 40, shr:0}], |
|||
[{in: [ 0, 0]}, {and: 0, or: 0, xor:0, not1:mask, shl: 0, shr:0}], |
|||
[{in: [-1, 1]}, {and: 0, or: m1m.add(bigInt.one), xor:m1m.add(bigInt.one), not1:mask.minus(m1m), shl: m1m.shiftLeft(1).and(mask), shr:__P__.shiftRight(1).and(mask)}], |
|||
] |
|||
); |
|||
}); |
|||
it("Logical ops", async () => { |
|||
await doTest( |
|||
"opslog.circom", |
|||
[ |
|||
[{in: [ 5, 0]}, {and: 0, or: 1, not1:0}], |
|||
[{in: [ 0, 1]}, {and: 0, or: 1, not1:1}], |
|||
[{in: [-1, 9]}, {and: 1, or: 1, not1:0}], |
|||
[{in: [ 0, 0]}, {and: 0, or: 0, not1:1}], |
|||
] |
|||
); |
|||
}); |
|||
|
|||
it("Conditional Ternary operator", async () => { |
|||
await doTest( |
|||
"condternary.circom", |
|||
[ |
|||
[{in: 0}, {out: 21}], |
|||
[{in: 1}, {out: 1}], |
|||
[{in: 2}, {out: 23}], |
|||
[{in:-1}, {out: 20}], |
|||
] |
|||
); |
|||
}); |
|||
|
|||
it("Compute block", async () => { |
|||
await doTest( |
|||
"compute.circom", |
|||
[ |
|||
[{x: 1}, {y: 7}], |
|||
[{x: 2}, {y: 7}], |
|||
[{x: 3}, {y: 11}], |
|||
[{x:-1}, {y: -5}], |
|||
] |
|||
); |
|||
}); |
|||
it("Component array ", async () => { |
|||
await doTest( |
|||
"componentarray.circom", |
|||
[ |
|||
[{in: 1}, {out: 1}], |
|||
[{in: 2}, {out: 256}], |
|||
[{in: 3}, {out: 6561}], |
|||
[{in:-1}, {out: 1}], |
|||
] |
|||
); |
|||
}); |
|||
it("Component array 2d", async () => { |
|||
await doTest( |
|||
"componentarray2.circom", |
|||
[ |
|||
[{in: [1,2]}, {out: [1, 256]}], |
|||
[{in: [0,3]}, {out: [0, 6561]}], |
|||
] |
|||
); |
|||
}); |
|||
it("Constant circuit", async () => { |
|||
await doTest( |
|||
"constantcircuit.circom", |
|||
[ |
|||
// 0xbb67ae85 |
|||
[{}, {out: [1,0,1,0, 0,0,0,1, 0,1,1,1, 0,1,0,1, 1,1,1,0, 0,1,1,0, 1,1,0,1, 1,1,0,1]}], |
|||
] |
|||
); |
|||
}); |
|||
it("Constant internal circuit", async () => { |
|||
await doTest( |
|||
"constantinternalcircuit.circom", |
|||
[ |
|||
[{in: 1}, {out: 5}], |
|||
[{in: 0}, {out: 4}], |
|||
[{in: -2}, {out: 2}], |
|||
[{in: 10}, {out: 14}] |
|||
] |
|||
); |
|||
}); |
|||
it("include", async () => { |
|||
await doTest( |
|||
"include.circom", |
|||
[ |
|||
[{in: 3}, {out: 6}], |
|||
[{in: 6}, {out: 15}], |
|||
] |
|||
); |
|||
}); |
|||
|
|||
}); |
@ -0,0 +1,307 @@ |
|||
[ |
|||
{ |
|||
"name": "inout", |
|||
"circuit": "inout.circom", |
|||
"tv": [ |
|||
[{ |
|||
"in1": 1, |
|||
"in2": [2,3], |
|||
"in3" : [[4,5], [6,7], [8,9]] |
|||
}, { |
|||
"out1": 1, |
|||
"out2": [2,3], |
|||
"out3": [[4,5], [6,7],[8,9]] |
|||
}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "add", |
|||
"circuit": "add.circom", |
|||
"tv": [ |
|||
[{"in": [0,0]}, {"out": 0}], |
|||
[{"in": [0 ,1]}, {"out": 1}], |
|||
[{"in": [1 ,2]}, {"out": 3}], |
|||
[{"in": [-1,1]}, {"out": 0}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "add constant", |
|||
"circuit": "addconst1.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 15}], |
|||
[{"in": 10}, {"out": 25}], |
|||
[{"in": -2}, {"out": 13}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "for unrolled", |
|||
"circuit": "forunrolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [ 0, 1, 2]}], |
|||
[{"in": 10}, {"out": [10, 11, 12]}], |
|||
[{"in": -2}, {"out": [-2, -1, 0]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "for rolled", |
|||
"circuit": "forrolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 0}], |
|||
[{"in": 10}, {"out": 10}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "while unrolled", |
|||
"circuit": "whileunrolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [ 0, 1, 2]}], |
|||
[{"in": 10}, {"out": [10, 11, 12]}], |
|||
[{"in": -2}, {"out": [-2, -1, 0]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "while rolled", |
|||
"circuit": "whilerolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 0}], |
|||
[{"in": 10}, {"out": 10}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "function1", |
|||
"circuit": "function1.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 3}], |
|||
[{"in": 10}, {"out": 13}], |
|||
[{"in": -2}, {"out": 1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "function2", |
|||
"circuit": "function2.circom", |
|||
"tv": [ |
|||
[{"in": 0 }, {"out": 3}], |
|||
[{"in": 10}, {"out": 13}], |
|||
[{"in": -2}, {"out": 1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "constants1", |
|||
"circuit": "constants1.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 42}], |
|||
[{"in": 10}, {"out": 52}], |
|||
[{"in": -2}, {"out": 40}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "arrays", |
|||
"circuit": "arrays.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [ 1, 8, 51]}], |
|||
[{"in": 10}, {"out": [11, 28, 111]}], |
|||
[{"in": -2}, {"out": [-1, 4, 39]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "if unrolled", |
|||
"circuit": "ifunrolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [ 1, 3, 6]}], |
|||
[{"in": 10}, {"out": [11, 13, 16]}], |
|||
[{"in": -2}, {"out": [-1, 1, 4]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "if rolled", |
|||
"circuit": "ifrolled.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [1, 0, 0]}], |
|||
[{"in": 1}, {"out": [0, 1, 0]}], |
|||
[{"in": 2}, {"out": [0, 0, 1]}], |
|||
[{"in": 3}, {"out": [0, 0, 0]}], |
|||
[{"in": -2}, {"out": [0, 0, 0]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "inc", |
|||
"circuit": "inc.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [5, 2]}], |
|||
[{"in": 1}, {"out": [6, 4]}], |
|||
[{"in": 2}, {"out": [7, 6]}], |
|||
[{"in": 3}, {"out": [8, 8]}], |
|||
[{"in": -2}, {"out": [3,-2]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "dec", |
|||
"circuit": "dec.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": [ 1, -2]}], |
|||
[{"in": 1}, {"out": [ 2, 0]}], |
|||
[{"in": 2}, {"out": [ 3, 2]}], |
|||
[{"in": 3}, {"out": [ 4, 4]}], |
|||
[{"in": -2}, {"out": [-1, -6]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "ops", |
|||
"circuit": "ops.circom", |
|||
"tv": [ |
|||
[{"in": [-2, 2]}, {"add": 0, "sub": -4, "mul": -4}], |
|||
[{"in": [-1, 1]}, {"add": 0, "sub": -2, "mul": -1}], |
|||
[{"in": [ 0, 0]}, {"add": 0, "sub": 0, "mul": 0}], |
|||
[{"in": [ 1,-1]}, {"add": 0, "sub": 2, "mul": -1}], |
|||
[{"in": [ 2,-2]}, {"add": 0, "sub": 4, "mul": -4}], |
|||
[{"in": [-2,-3]}, {"add": -5, "sub": 1, "mul": 6}], |
|||
[{"in": [ 2, 3]}, {"add": 5, "sub": -1, "mul": 6}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "ops2", |
|||
"circuit": "ops2.circom", |
|||
"tv": [ |
|||
[{"in": [-2, 2]}, {"div": -1, "idiv": "10944121435919637611123202872628637544274182200208017171849102093287904247807", "mod": 1}], |
|||
[{"in": [-1, 1]}, {"div": -1, "idiv": -1, "mod": 0}], |
|||
[{"in": [ 1,-1]}, {"div": -1, "idiv": 0, "mod": 1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "ops3", |
|||
"circuit": "ops3.circom", |
|||
"tv": [ |
|||
[{"in": [-2, 2]}, {"neg1": 2, "neg2": -2, "pow": 4}], |
|||
[{"in": [ 0, 1]}, {"neg1": 0, "neg2": -1, "pow": 0}], |
|||
[{"in": [ 1,-1]}, {"neg1": -1, "neg2": 1, "pow": 1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Comparation ops", |
|||
"circuit": "opscmp.circom", |
|||
"tv": [ |
|||
[{"in": [ 8, 9]}, {"lt": 1, "leq": 1, "eq":0, "neq":1, "geq": 0, "gt":0}], |
|||
[{"in": [-2,-2]}, {"lt": 0, "leq": 1, "eq":1, "neq":0, "geq": 1, "gt":0}], |
|||
[{"in": [-1,-2]}, {"lt": 0, "leq": 0, "eq":0, "neq":1, "geq": 1, "gt":1}], |
|||
[{"in": [ 1,-1]}, {"lt": 0, "leq": 0, "eq":0, "neq":1, "geq": 1, "gt":1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Bit ops", |
|||
"circuit": "opsbit.circom", |
|||
"tv": [ |
|||
[ |
|||
{ |
|||
"in": [ 5, 3] |
|||
}, |
|||
{ |
|||
"and": 1, |
|||
"or": 7, |
|||
"xor":6, |
|||
"not1": "14474011154664524427946373126085988481658748083205070504932198000989141204986", |
|||
"shl": 40, |
|||
"shr":0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"in": [ 0, 0] |
|||
}, |
|||
{ |
|||
"and": 0, |
|||
"or": 0, |
|||
"xor":0, |
|||
"not1":"14474011154664524427946373126085988481658748083205070504932198000989141204991", |
|||
"shl": 0, |
|||
"shr":0 |
|||
} |
|||
], |
|||
[ |
|||
{ |
|||
"in": [-1, 1] |
|||
}, |
|||
{ |
|||
"and": 0, |
|||
"or": "7414231717174750794300032619171286606889616317210963838766006185586667290625", |
|||
"xor":"7414231717174750794300032619171286606889616317210963838766006185586667290625", |
|||
"not1": "7059779437489773633646340506914701874769131765994106666166191815402473914367", |
|||
"shl": "354452279684977160653692112256584732120484551216857172599814370184193376256", |
|||
"shr": "10944121435919637611123202872628637544274182200208017171849102093287904247808" |
|||
} |
|||
] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Logical ops", |
|||
"circuit": "opslog.circom", |
|||
"tv": [ |
|||
[{"in": [ 5, 0]}, {"and": 0, "or": 1, "not1":0}], |
|||
[{"in": [ 0, 1]}, {"and": 0, "or": 1, "not1":1}], |
|||
[{"in": [-1, 9]}, {"and": 1, "or": 1, "not1":0}], |
|||
[{"in": [ 0, 0]}, {"and": 0, "or": 0, "not1":1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Conditional Ternary operator", |
|||
"circuit": "condternary.circom", |
|||
"tv": [ |
|||
[{"in": 0}, {"out": 21}], |
|||
[{"in": 1}, {"out": 1}], |
|||
[{"in": 2}, {"out": 23}], |
|||
[{"in":-1}, {"out": 20}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Compute block", |
|||
"circuit": "compute.circom", |
|||
"tv": [ |
|||
[{"x": 1}, {"y": 7}], |
|||
[{"x": 2}, {"y": 7}], |
|||
[{"x": 3}, {"y": 11}], |
|||
[{"x":-1}, {"y": -5}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Component array", |
|||
"circuit": "componentarray.circom", |
|||
"tv": [ |
|||
[{"in": 1}, {"out": 1}], |
|||
[{"in": 2}, {"out": 256}], |
|||
[{"in": 3}, {"out": 6561}], |
|||
[{"in":-1}, {"out": 1}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Component array 2d", |
|||
"circuit": "componentarray2.circom", |
|||
"tv": [ |
|||
[{"in": [1,2]}, {"out": [1, 256]}], |
|||
[{"in": [0,3]}, {"out": [0, 6561]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Constant circuit", |
|||
"circuit": "constantcircuit.circom", |
|||
"tv": [ |
|||
[{}, {"out": [1,0,1,0, 0,0,0,1, 0,1,1,1, 0,1,0,1, 1,1,1,0, 0,1,1,0, 1,1,0,1, 1,1,0,1]}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "Constant internal circuit", |
|||
"circuit": "constantinternalcircuit.circom", |
|||
"tv": [ |
|||
[{"in": 1}, {"out": 5}], |
|||
[{"in": 0}, {"out": 4}], |
|||
[{"in": -2}, {"out": 2}], |
|||
[{"in": 10}, {"out": 14}] |
|||
] |
|||
}, |
|||
{ |
|||
"name": "include", |
|||
"circuit": "include.circom", |
|||
"tv": [ |
|||
[{"in": 3}, {"out": 6}], |
|||
[{"in": 6}, {"out": 15}] |
|||
] |
|||
} |
|||
] |
@ -1 +0,0 @@ |
|||
{"x": "3"} |