diff --git a/c/buildasm/fr.o b/c/buildasm/fr.o deleted file mode 100644 index e352655..0000000 Binary files a/c/buildasm/fr.o and /dev/null differ diff --git a/c/mainjson b/c/mainjson deleted file mode 100644 index 3809f76..0000000 Binary files a/c/mainjson and /dev/null differ diff --git a/cli.js b/cli.js index b00bc22..bf56050 100755 --- a/cli.js +++ b/cli.js @@ -34,6 +34,7 @@ const argv = require("yargs") .alias("o", "output") .alias("c", "csource") .alias("w", "wasm") + .alias("t", "wat") .alias("s", "sym") .alias("r", "r1cs") .alias("n", "newThreadTemplates") @@ -71,6 +72,7 @@ const fullFileName = path.resolve(process.cwd(), inputFile); const fileName = path.basename(fullFileName, ".circom"); const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp"; const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm"; +const watName = typeof(argv.wat) === "string" ? argv.wat : fileName + ".wat"; const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs"; const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym"; @@ -83,6 +85,9 @@ if (argv.csource) { if (argv.wasm) { options.wasmWriteStream = fs.createWriteStream(wasmName); } +if (argv.wat) { + options.watWriteStream = fs.createWriteStream(watName); +} if (argv.r1cs) { options.r1csFileName = r1csName; } @@ -97,6 +102,7 @@ compiler(fullFileName, options).then( () => { let cSourceDone = false; let wasmDone = false; let symDone = false; + let watDone = false; if (options.cSourceWriteStream) { options.cSourceWriteStream.on("finish", () => { cSourceDone = true; @@ -113,6 +119,14 @@ compiler(fullFileName, options).then( () => { } else { wasmDone = true; } + if (options.watWriteStream) { + options.watWriteStream.on("finish", () => { + watDone = true; + finishIfDone(); + }); + } else { + watDone = true; + } if (options.symWriteStream) { options.symWriteStream.on("finish", () => { symDone = true; @@ -122,7 +136,7 @@ compiler(fullFileName, options).then( () => { symDone = true; } function finishIfDone() { - if ((cSourceDone)&&(symDone)&&(wasmDone)) { + if ((cSourceDone)&&(symDone)&&(wasmDone)&&(watDone)) { setTimeout(() => { process.exit(0); }, 300); diff --git a/index.js b/index.js index 83d1192..a75c4a3 100644 --- a/index.js +++ b/index.js @@ -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"); diff --git a/package-lock.json b/package-lock.json index c61bcc0..87e037c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1482,6 +1482,14 @@ "punycode": "^2.1.0" } }, + "wasmbuilder": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.8.tgz", + "integrity": "sha512-d63cIsDmHnybA5hTlRRLadgys5r3Tl4W8SbcBRh13FauEPOo48dqjgzdL1xefpZkpKKybDRlFqgm+9cX04B3+w==", + "requires": { + "big-integer": "^1.6.43" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 25ae4ff..65df8bf 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "optimist": "^0.6.1", "rimraf-promise": "^2.0.0", "tmp-promise": "^2.0.2", + "wasmbuilder": "0.0.8", "yargs": "^12.0.2" }, "devDependencies": { diff --git a/c/buildasm/add.asm.ejs b/ports/c/buildasm/add.asm.ejs similarity index 100% rename from c/buildasm/add.asm.ejs rename to ports/c/buildasm/add.asm.ejs diff --git a/c/buildasm/binops.asm.ejs b/ports/c/buildasm/binops.asm.ejs similarity index 100% rename from c/buildasm/binops.asm.ejs rename to ports/c/buildasm/binops.asm.ejs diff --git a/c/buildasm/buildzqfield.js b/ports/c/buildasm/buildzqfield.js similarity index 100% rename from c/buildasm/buildzqfield.js rename to ports/c/buildasm/buildzqfield.js diff --git a/c/buildasm/buildzqfieldtester.js b/ports/c/buildasm/buildzqfieldtester.js similarity index 100% rename from c/buildasm/buildzqfieldtester.js rename to ports/c/buildasm/buildzqfieldtester.js diff --git a/ports/c/buildasm/cmpops.asm.ejs b/ports/c/buildasm/cmpops.asm.ejs new file mode 100644 index 0000000..2c6a324 --- /dev/null +++ b/ports/c/buildasm/cmpops.asm.ejs @@ -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 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 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 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 + mov rax, [rsi + <%= 8+(i*8) %>] + cmp [rdx + <%= 8+(i*8) %>], rax + jne req_ret0 ; rsi 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 diff --git a/c/buildasm/cmpops.asm.ejs b/ports/c/buildasm/cmpops_old.asm.ejs similarity index 98% rename from c/buildasm/cmpops.asm.ejs rename to ports/c/buildasm/cmpops_old.asm.ejs index 183bd55..420bdce 100644 --- a/c/buildasm/cmpops.asm.ejs +++ b/ports/c/buildasm/cmpops_old.asm.ejs @@ -40,7 +40,7 @@ ;;;;;;;;;;;;;;;;;;;;;; ; <%= op %> ;;;;;;;;;;;;;;;;;;;;;; -; Adds two elements of any kind +; Compares two elements of any kind ; Params: ; rsi <= Pointer to element 1 ; rdx <= Pointer to element 2 diff --git a/c/buildasm/copy.asm.ejs b/ports/c/buildasm/copy.asm.ejs similarity index 95% rename from c/buildasm/copy.asm.ejs rename to ports/c/buildasm/copy.asm.ejs index 6f469b1..a9623ed 100644 --- a/c/buildasm/copy.asm.ejs +++ b/ports/c/buildasm/copy.asm.ejs @@ -97,6 +97,12 @@ u64toLong_adjust_neg: ret <%=name%>_long: + bt rax, 62 + jnc <%=name%>_longNormal +<%=name%>_longMontgomery: + call <%=name%>_toLongNormal + +<%=name%>_longNormal: mov rax, [rdi + 8] mov rcx, rax shr rcx, 31 diff --git a/c/buildasm/fr.asm b/ports/c/buildasm/fr.asm similarity index 84% rename from c/buildasm/fr.asm rename to ports/c/buildasm/fr.asm index 597b1b6..ceb7538 100644 --- a/c/buildasm/fr.asm +++ b/ports/c/buildasm/fr.asm @@ -46,7 +46,6 @@ - ;;;;;;;;;;;;;;;;;;;;;; ; copy ;;;;;;;;;;;;;;;;;;;;;; @@ -170,6 +169,12 @@ Fr_toInt: ret Fr_long: + bt rax, 62 + jnc Fr_longNormal +Fr_longMontgomery: + call Fr_toLongNormal + +Fr_longNormal: mov rax, [rdi + 8] mov rcx, rax shr rcx, 31 @@ -4713,787 +4718,469 @@ bnot_l1n: - - - - - - - ;;;;;;;;;;;;;;;;;;;;;; -; eq +; rgt - Raw Greater Than ;;;;;;;;;;;;;;;;;;;;;; -; Adds two elements of any kind +; returns in ax 1 id *rsi > *rdx ; Params: ; rsi <= Pointer to element 1 ; rdx <= Pointer to element 2 -; rdi <= Pointer to result can be zero or one. +; rax <= Return 1 or 0 ; Modified Registers: -; r8, r9, 10, r11, rax, rcx +; r8, r9, rax ;;;;;;;;;;;;;;;;;;;;;; -Fr_eq: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc eq_longCmp - -eq_shortCmp: - cmp eax, 0 - je eq_s_eq - js eq_s_lt -eq_s_gt: - - mov qword [rdi], 0 - add rsp, 40 - ret - -eq_s_lt: - - mov qword [rdi], 0 - add rsp, 40 - ret - -eq_s_eq: - - mov qword [rdi], 1 - add rsp, 40 - ret - - -eq_longCmp: - - - cmp qword [rsp + 32], 0 - jnz eq_neq - - cmp qword [rsp + 24], 0 - jnz eq_neq +Fr_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 - cmp qword [rsp + 16], 0 - jnz eq_neq +rgt_s1s2: ; Both operands are short + cmp r8d, r9d + jg rgt_ret1 + jmp rgt_ret0 - cmp qword [rsp + 8], 0 - jnz eq_neq -eq_eq: +rgt_l1: + bt r9, 63 ; Check if is short second operand + jc rgt_l1l2 - mov qword [rdi], 1 - add rsp, 40 - ret +;;;;;;;; +rgt_l1s2: + bt r8, 62 ; check if montgomery first + jc rgt_l1ms2 +rgt_l1ns2: + push rdi + push rsi + mov rdi, rdx + movsx rsi, r9d + call rawCopyS2L + mov rdx, rdi + pop rsi + pop rdi + jmp rgtL1L2 -eq_neq: +rgt_l1ms2: + push rdi + push rsi + mov rdi, rdx + movsx rsi, r9d + call rawCopyS2L + mov rdx, rdi + pop rsi + pop rdi + push rdi + mov rdi, rsi + mov rsi, rdx + call Fr_toNormal + mov rdx, rsi + mov rsi, rdi + pop rdi + jmp rgtL1L2 - mov qword [rdi], 0 - add rsp, 40 - ret +;;;;;;;; +rgt_s1l2: + bt r9, 62 ; check if montgomery second + jc rgt_s1l2m +rgt_s1l2n: + push rdi + push rdx + mov rdi, rsi + movsx rsi, r8d + call rawCopyS2L + mov rsi, rdi + pop rdx + pop rdi + jmp rgtL1L2 +rgt_s1l2m: + push rdi + push rdx + mov rdi, rsi + movsx rsi, r8d + call rawCopyS2L + mov rsi, rdi + pop rdx + pop rdi + push rdi + mov rdi, rdx + call Fr_toNormal + mov rdx, rdi + pop rdi + 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: + push rdi + mov rdi, rdx + call Fr_toNormal + mov rdx, rdi + pop rdi + jmp rgtL1L2 -;;;;;;;;;;;;;;;;;;;;;; -; neq -;;;;;;;;;;;;;;;;;;;;;; -; Adds 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: -; r8, r9, 10, r11, rax, rcx -;;;;;;;;;;;;;;;;;;;;;; -Fr_neq: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc neq_longCmp - -neq_shortCmp: - cmp eax, 0 - je neq_s_eq - js neq_s_lt -neq_s_gt: +rgt_l1ml2: + bt r9, 62 ; check if montgomery second + jc rgt_l1ml2m +rgt_l1ml2n: + push rdi + mov rdi, rsi + mov rsi, rdx + call Fr_toNormal + mov rdx, rsi + mov rsi, rdi + pop rdi + jmp rgtL1L2 - mov qword [rdi], 1 - add rsp, 40 - ret +rgt_l1ml2m: + push rdi + mov rdi, rsi + mov rsi, rdx + call Fr_toNormal + mov rdx, rsi + mov rsi, rdi + pop rdi + push rdi + mov rdi, rdx + call Fr_toNormal + mov rdx, rdi + pop rdi + jmp rgtL1L2 -neq_s_lt: - mov qword [rdi], 1 - add rsp, 40 - ret +;;;;;; +; rgtL1L2 +;;;;;; -neq_s_eq: +rgtL1L2: - mov qword [rdi], 0 - add rsp, 40 - ret + mov rax, [rsi + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 -neq_longCmp: + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 - cmp qword [rsp + 32], 0 - jnz neq_neq + mov rax, [rsi + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 - cmp qword [rsp + 24], 0 - jnz neq_neq + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 - cmp qword [rsp + 16], 0 - jnz neq_neq - cmp qword [rsp + 8], 0 - jnz neq_neq + mov rax, [rsi + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 -neq_eq: + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 - mov qword [rdi], 0 - add rsp, 40 - ret -neq_neq: + mov rax, [rsi + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 - mov qword [rdi], 1 - add rsp, 40 - ret + jmp rgtl1l2_p1 +rgtl1l2_p1: -;;;;;;;;;;;;;;;;;;;;;; -; lt -;;;;;;;;;;;;;;;;;;;;;; -; Adds 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: -; r8, r9, 10, r11, rax, rcx -;;;;;;;;;;;;;;;;;;;;;; -Fr_lt: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc lt_longCmp - -lt_shortCmp: - cmp eax, 0 - je lt_s_eq - js lt_s_lt -lt_s_gt: + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 - mov qword [rdi], 0 - add rsp, 40 - ret + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 -lt_s_lt: - mov qword [rdi], 1 - add rsp, 40 - ret + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 -lt_s_eq: + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 - mov qword [rdi], 0 - add rsp, 40 - ret + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 -lt_longCmp: + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 - cmp qword [rsp + 32], 0 - jnz lt_neq + mov rax, [rdx + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 - cmp qword [rsp + 24], 0 - jnz lt_neq + jmp rgtRawL1L2 - cmp qword [rsp + 16], 0 - jnz lt_neq - cmp qword [rsp + 8], 0 - jnz lt_neq -lt_eq: +rgtl1l2_n1: - mov qword [rdi], 0 - add rsp, 40 - ret + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_29 ; half e1-e2 is neg => e1 < e2 - jnz tmp_28 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_29 ; half e1-e2 is neg => e1 < e2 - jnz tmp_28 ; half>rax => e1 -e2 is pos => e1 > e2 + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_29 ; half e1-e2 is neg => e1 < e2 - jnz tmp_28 ; half>rax => e1 -e2 is pos => e1 > e2 - mov rax, [rsp + 8] + mov rax, [rdx + 8] cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_29 ; half e1-e2 is neg => e1 < e2 - jnz tmp_28 ; half>rax => e1 -e2 is pos => e1 > e2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_28: + jmp rgt_ret0 - mov qword [rdi], 0 - add rsp, 40 - ret -tmp_29: - mov qword [rdi], 1 - add rsp, 40 - ret -lt_neq: +rgtRawL1L2: + mov rax, [rsi + 32] + cmp [rdx + 32], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 24] + cmp [rdx + 24], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 16] + cmp [rdx + 16], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_31 ; half e1-e2 is neg => e1 < e2 - jnz tmp_30 ; half>rax => e1 -e2 is pos => e1 > e2 + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_31 ; half e1-e2 is neg => e1 < e2 - jnz tmp_30 ; half>rax => e1 -e2 is pos => e1 > e2 - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_31 ; half e1-e2 is neg => e1 < e2 - jnz tmp_30 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 8] + cmp [rdx + 8], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_31 ; half e1-e2 is neg => e1 < e2 - jnz tmp_30 ; half>rax => e1 -e2 is pos => e1 > e2 - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_30: - mov qword [rdi], 0 - add rsp, 40 +rgt_ret0: + xor rax, rax ret - -tmp_31: - - mov qword [rdi], 1 - add rsp, 40 +rgt_ret1: + mov rax, 1 ret - - - ;;;;;;;;;;;;;;;;;;;;;; -; gt +; req - Raw Eq ;;;;;;;;;;;;;;;;;;;;;; -; Adds two elements of any kind +; returns in ax 1 id *rsi == *rdx ; Params: ; rsi <= Pointer to element 1 ; rdx <= Pointer to element 2 -; rdi <= Pointer to result can be zero or one. +; rax <= Return 1 or 0 ; Modified Registers: -; r8, r9, 10, r11, rax, rcx +; r8, r9, rax ;;;;;;;;;;;;;;;;;;;;;; -Fr_gt: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc gt_longCmp - -gt_shortCmp: - cmp eax, 0 - je gt_s_eq - js gt_s_lt -gt_s_gt: - - mov qword [rdi], 1 - add rsp, 40 - ret - -gt_s_lt: - - mov qword [rdi], 0 - add rsp, 40 - ret - -gt_s_eq: - - mov qword [rdi], 0 - add rsp, 40 - ret +Fr_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 -gt_longCmp: +req_l1: + bt r9, 63 ; Check if is short second operand + jc req_l1l2 - cmp qword [rsp + 32], 0 - jnz gt_neq +;;;;;;;; +req_l1s2: + bt r8, 62 ; check if montgomery first + jc req_l1ms2 +req_l1ns2: + push rdi + push rsi + mov rdi, rdx + movsx rsi, r9d + call rawCopyS2L + mov rdx, rdi + pop rsi + pop rdi + jmp reqL1L2 - cmp qword [rsp + 24], 0 - jnz gt_neq +req_l1ms2: + push rdi + mov rdi, rdx + call Fr_toMontgomery + mov rdx, rdi + pop rdi + jmp reqL1L2 - cmp qword [rsp + 16], 0 - jnz gt_neq - cmp qword [rsp + 8], 0 - jnz gt_neq +;;;;;;;; +req_s1l2: + bt r9, 62 ; check if montgomery second + jc req_s1l2m +req_s1l2n: + push rdi + push rdx + mov rdi, rsi + movsx rsi, r8d + call rawCopyS2L + mov rsi, rdi + pop rdx + pop rdi + jmp reqL1L2 -gt_eq: - - - - mov qword [rdi], 0 - add rsp, 40 - ret - - - - - - - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_33 ; half e1-e2 is neg => e1 < e2 - jnz tmp_32 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_33 ; half e1-e2 is neg => e1 < e2 - jnz tmp_32 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_33 ; half e1-e2 is neg => e1 < e2 - jnz tmp_32 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_33 ; half e1-e2 is neg => e1 < e2 - jnz tmp_32 ; half>rax => e1 -e2 is pos => e1 > e2 - - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_32: - - mov qword [rdi], 1 - add rsp, 40 - ret - -tmp_33: - - mov qword [rdi], 0 - add rsp, 40 - ret - - -gt_neq: +req_s1l2m: + push rdi + mov rdi, rsi + mov rsi, rdx + call Fr_toMontgomery + mov rdx, rsi + mov rsi, rdi + pop rdi + 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: + push rdi + mov rdi, rsi + mov rsi, rdx + call Fr_toMontgomery + mov rdx, rsi + mov rsi, rdi + pop rdi + jmp reqL1L2 +req_l1ml2: + bt r9, 62 ; check if montgomery second + jc req_l1ml2m +req_l1ml2n: + push rdi + mov rdi, rdx + call Fr_toMontgomery + mov rdx, rdi + pop rdi + jmp reqL1L2 +req_l1ml2m: + jmp reqL1L2 +;;;;;; +; eqL1L2 +;;;;;; +reqL1L2: - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_35 ; half e1-e2 is neg => e1 < e2 - jnz tmp_34 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 8] + cmp [rdx + 8], rax + jne req_ret0 ; rsi 1st > 2nd - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_35 ; half e1-e2 is neg => e1 < e2 - jnz tmp_34 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 16] + cmp [rdx + 16], rax + jne req_ret0 ; rsi 1st > 2nd - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_35 ; half e1-e2 is neg => e1 < e2 - jnz tmp_34 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 24] + cmp [rdx + 24], rax + jne req_ret0 ; rsi 1st > 2nd - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_35 ; half e1-e2 is neg => e1 < e2 - jnz tmp_34 ; half>rax => e1 -e2 is pos => e1 > e2 + mov rax, [rsi + 32] + cmp [rdx + 32], rax + jne req_ret0 ; rsi 1st > 2nd - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_34: - mov qword [rdi], 1 - add rsp, 40 +req_ret1: + mov rax, 1 ret -tmp_35: - - mov qword [rdi], 0 - add rsp, 40 +req_ret0: + xor rax, rax ret - - - - ;;;;;;;;;;;;;;;;;;;;;; -; leq +; gt ;;;;;;;;;;;;;;;;;;;;;; -; Adds two elements of any kind +; 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: -; r8, r9, 10, r11, rax, rcx +; rax, rcx ;;;;;;;;;;;;;;;;;;;;;; -Fr_leq: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc leq_longCmp - -leq_shortCmp: - cmp eax, 0 - je leq_s_eq - js leq_s_lt -leq_s_gt: - - mov qword [rdi], 0 - add rsp, 40 - ret - -leq_s_lt: - - mov qword [rdi], 1 - add rsp, 40 - ret - -leq_s_eq: - - mov qword [rdi], 1 - add rsp, 40 - ret - - -leq_longCmp: - - - cmp qword [rsp + 32], 0 - jnz leq_neq - - cmp qword [rsp + 24], 0 - jnz leq_neq - - cmp qword [rsp + 16], 0 - jnz leq_neq - - cmp qword [rsp + 8], 0 - jnz leq_neq - -leq_eq: - - - - mov qword [rdi], 1 - add rsp, 40 - ret - - - - - - - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_37 ; half e1-e2 is neg => e1 < e2 - jnz tmp_36 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_37 ; half e1-e2 is neg => e1 < e2 - jnz tmp_36 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_37 ; half e1-e2 is neg => e1 < e2 - jnz tmp_36 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_37 ; half e1-e2 is neg => e1 < e2 - jnz tmp_36 ; half>rax => e1 -e2 is pos => e1 > e2 - - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_36: - - mov qword [rdi], 0 - add rsp, 40 - ret - -tmp_37: - - mov qword [rdi], 1 - add rsp, 40 - ret - - -leq_neq: - - - - - - - - - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_39 ; half e1-e2 is neg => e1 < e2 - jnz tmp_38 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_39 ; half e1-e2 is neg => e1 < e2 - jnz tmp_38 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_39 ; half e1-e2 is neg => e1 < e2 - jnz tmp_38 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_39 ; half e1-e2 is neg => e1 < e2 - jnz tmp_38 ; half>rax => e1 -e2 is pos => e1 > e2 - - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_38: - - mov qword [rdi], 0 - add rsp, 40 - ret - -tmp_39: - - mov qword [rdi], 1 - add rsp, 40 +Fr_gt: + call Fr_rgt + mov [rdi], rax ret - - - - - ;;;;;;;;;;;;;;;;;;;;;; -; geq +; eq ;;;;;;;;;;;;;;;;;;;;;; -; Adds two elements of any kind +; 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: -; r8, r9, 10, r11, rax, rcx +; rax, rcx ;;;;;;;;;;;;;;;;;;;;;; -Fr_geq: - sub rsp, 40 ; Save space for the result of the substraction - push rdi ; Save rdi - lea rdi, [rsp+8] ; We pushed rdi so we need to add 8 - call Fr_sub ; Do a substraction - call Fr_toNormal ; Convert it to normal - pop rdi - - mov rax, [rsp] ; We already poped do no need to add 8 - bt rax, 63 ; check is result is long - jc geq_longCmp - -geq_shortCmp: - cmp eax, 0 - je geq_s_eq - js geq_s_lt -geq_s_gt: - - mov qword [rdi], 1 - add rsp, 40 - ret - -geq_s_lt: - - mov qword [rdi], 0 - add rsp, 40 - ret - -geq_s_eq: - - mov qword [rdi], 1 - add rsp, 40 - ret - - -geq_longCmp: - - - cmp qword [rsp + 32], 0 - jnz geq_neq - - cmp qword [rsp + 24], 0 - jnz geq_neq - - cmp qword [rsp + 16], 0 - jnz geq_neq - - cmp qword [rsp + 8], 0 - jnz geq_neq - -geq_eq: - - - - mov qword [rdi], 1 - add rsp, 40 - ret - - - - - - - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_41 ; half e1-e2 is neg => e1 < e2 - jnz tmp_40 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_41 ; half e1-e2 is neg => e1 < e2 - jnz tmp_40 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_41 ; half e1-e2 is neg => e1 < e2 - jnz tmp_40 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_41 ; half e1-e2 is neg => e1 < e2 - jnz tmp_40 ; half>rax => e1 -e2 is pos => e1 > e2 - - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_40: - - mov qword [rdi], 1 - add rsp, 40 - ret - -tmp_41: - - mov qword [rdi], 0 - add rsp, 40 - ret - - -geq_neq: - - - - - - - - - mov rax, [rsp + 32] - cmp [half + 24], rax ; comare with (q-1)/2 - jc tmp_43 ; half e1-e2 is neg => e1 < e2 - jnz tmp_42 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 24] - cmp [half + 16], rax ; comare with (q-1)/2 - jc tmp_43 ; half e1-e2 is neg => e1 < e2 - jnz tmp_42 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 16] - cmp [half + 8], rax ; comare with (q-1)/2 - jc tmp_43 ; half e1-e2 is neg => e1 < e2 - jnz tmp_42 ; half>rax => e1 -e2 is pos => e1 > e2 - - mov rax, [rsp + 8] - cmp [half + 0], rax ; comare with (q-1)/2 - jc tmp_43 ; half e1-e2 is neg => e1 < e2 - jnz tmp_42 ; half>rax => e1 -e2 is pos => e1 > e2 - - ; half == rax => e1-e2 is pos => e1 > e2 -tmp_42: - - mov qword [rdi], 1 - add rsp, 40 - ret - -tmp_43: - - mov qword [rdi], 0 - add rsp, 40 +Fr_eq: + call Fr_req + mov [rdi], rax ret - - - - - +Fr_geq: +Fr_leq: +Fr_lt: +Fr_neq: @@ -5525,39 +5212,39 @@ Fr_land: mov rax, [rsi] bt rax, 63 - jc tmp_44 + jc tmp_28 test eax, eax - jz retZero_46 - jmp retOne_45 + jz retZero_30 + jmp retOne_29 -tmp_44: +tmp_28: mov rax, [rsi + 8] test rax, rax - jnz retOne_45 + jnz retOne_29 mov rax, [rsi + 16] test rax, rax - jnz retOne_45 + jnz retOne_29 mov rax, [rsi + 24] test rax, rax - jnz retOne_45 + jnz retOne_29 mov rax, [rsi + 32] test rax, rax - jnz retOne_45 + jnz retOne_29 -retZero_46: +retZero_30: mov qword r8, 0 - jmp done_47 + jmp done_31 -retOne_45: +retOne_29: mov qword r8, 1 -done_47: +done_31: @@ -5567,39 +5254,39 @@ done_47: mov rax, [rdx] bt rax, 63 - jc tmp_48 + jc tmp_32 test eax, eax - jz retZero_50 - jmp retOne_49 + jz retZero_34 + jmp retOne_33 -tmp_48: +tmp_32: mov rax, [rdx + 8] test rax, rax - jnz retOne_49 + jnz retOne_33 mov rax, [rdx + 16] test rax, rax - jnz retOne_49 + jnz retOne_33 mov rax, [rdx + 24] test rax, rax - jnz retOne_49 + jnz retOne_33 mov rax, [rdx + 32] test rax, rax - jnz retOne_49 + jnz retOne_33 -retZero_50: +retZero_34: mov qword rcx, 0 - jmp done_51 + jmp done_35 -retOne_49: +retOne_33: mov qword rcx, 1 -done_51: +done_35: and rcx, r8 mov [rdi], rcx @@ -5626,39 +5313,39 @@ Fr_lor: mov rax, [rsi] bt rax, 63 - jc tmp_52 + jc tmp_36 test eax, eax - jz retZero_54 - jmp retOne_53 + jz retZero_38 + jmp retOne_37 -tmp_52: +tmp_36: mov rax, [rsi + 8] test rax, rax - jnz retOne_53 + jnz retOne_37 mov rax, [rsi + 16] test rax, rax - jnz retOne_53 + jnz retOne_37 mov rax, [rsi + 24] test rax, rax - jnz retOne_53 + jnz retOne_37 mov rax, [rsi + 32] test rax, rax - jnz retOne_53 + jnz retOne_37 -retZero_54: +retZero_38: mov qword r8, 0 - jmp done_55 + jmp done_39 -retOne_53: +retOne_37: mov qword r8, 1 -done_55: +done_39: @@ -5668,39 +5355,39 @@ done_55: mov rax, [rdx] bt rax, 63 - jc tmp_56 + jc tmp_40 test eax, eax - jz retZero_58 - jmp retOne_57 + jz retZero_42 + jmp retOne_41 -tmp_56: +tmp_40: mov rax, [rdx + 8] test rax, rax - jnz retOne_57 + jnz retOne_41 mov rax, [rdx + 16] test rax, rax - jnz retOne_57 + jnz retOne_41 mov rax, [rdx + 24] test rax, rax - jnz retOne_57 + jnz retOne_41 mov rax, [rdx + 32] test rax, rax - jnz retOne_57 + jnz retOne_41 -retZero_58: +retZero_42: mov qword rcx, 0 - jmp done_59 + jmp done_43 -retOne_57: +retOne_41: mov qword rcx, 1 -done_59: +done_43: or rcx, r8 mov [rdi], rcx @@ -5726,39 +5413,39 @@ Fr_lnot: mov rax, [rsi] bt rax, 63 - jc tmp_60 + jc tmp_44 test eax, eax - jz retZero_62 - jmp retOne_61 + jz retZero_46 + jmp retOne_45 -tmp_60: +tmp_44: mov rax, [rsi + 8] test rax, rax - jnz retOne_61 + jnz retOne_45 mov rax, [rsi + 16] test rax, rax - jnz retOne_61 + jnz retOne_45 mov rax, [rsi + 24] test rax, rax - jnz retOne_61 + jnz retOne_45 mov rax, [rsi + 32] test rax, rax - jnz retOne_61 + jnz retOne_45 -retZero_62: +retZero_46: mov qword rcx, 0 - jmp done_63 + jmp done_47 -retOne_61: +retOne_45: mov qword rcx, 1 -done_63: +done_47: test rcx, rcx @@ -5789,39 +5476,39 @@ Fr_isTrue: mov rax, [rdi] bt rax, 63 - jc tmp_64 + jc tmp_48 test eax, eax - jz retZero_66 - jmp retOne_65 + jz retZero_50 + jmp retOne_49 -tmp_64: +tmp_48: mov rax, [rdi + 8] test rax, rax - jnz retOne_65 + jnz retOne_49 mov rax, [rdi + 16] test rax, rax - jnz retOne_65 + jnz retOne_49 mov rax, [rdi + 24] test rax, rax - jnz retOne_65 + jnz retOne_49 mov rax, [rdi + 32] test rax, rax - jnz retOne_65 + jnz retOne_49 -retZero_66: +retZero_50: mov qword rax, 0 - jmp done_67 + jmp done_51 -retOne_65: +retOne_49: mov qword rax, 1 -done_67: +done_51: ret diff --git a/c/buildasm/fr.asm.ejs b/ports/c/buildasm/fr.asm.ejs similarity index 100% rename from c/buildasm/fr.asm.ejs rename to ports/c/buildasm/fr.asm.ejs diff --git a/c/buildasm/fr.c b/ports/c/buildasm/fr.c similarity index 99% rename from c/buildasm/fr.c rename to ports/c/buildasm/fr.c index 62c4d57..dca448b 100644 --- a/c/buildasm/fr.c +++ b/ports/c/buildasm/fr.c @@ -63,7 +63,6 @@ char *Fr_element2str(PFrElement pE) { } else { mpz_init_set_si(r, pE->shortVal); mpz_add(r, r, q); - mpz_clear(q); } } else { Fr_toNormal(pE); diff --git a/c/buildasm/fr.c.ejs b/ports/c/buildasm/fr.c.ejs similarity index 100% rename from c/buildasm/fr.c.ejs rename to ports/c/buildasm/fr.c.ejs diff --git a/c/buildasm/fr.h b/ports/c/buildasm/fr.h similarity index 100% rename from c/buildasm/fr.h rename to ports/c/buildasm/fr.h diff --git a/c/buildasm/fr.h.ejs b/ports/c/buildasm/fr.h.ejs similarity index 100% rename from c/buildasm/fr.h.ejs rename to ports/c/buildasm/fr.h.ejs diff --git a/ports/c/buildasm/fr.o b/ports/c/buildasm/fr.o new file mode 100644 index 0000000..bffc8de Binary files /dev/null and b/ports/c/buildasm/fr.o differ diff --git a/c/buildasm/logicalops.asm.ejs b/ports/c/buildasm/logicalops.asm.ejs similarity index 100% rename from c/buildasm/logicalops.asm.ejs rename to ports/c/buildasm/logicalops.asm.ejs diff --git a/c/buildasm/main.c b/ports/c/buildasm/main.c similarity index 100% rename from c/buildasm/main.c rename to ports/c/buildasm/main.c diff --git a/c/buildasm/montgomery.asm.ejs b/ports/c/buildasm/montgomery.asm.ejs similarity index 100% rename from c/buildasm/montgomery.asm.ejs rename to ports/c/buildasm/montgomery.asm.ejs diff --git a/c/buildasm/mul.asm.ejs b/ports/c/buildasm/mul.asm.ejs similarity index 100% rename from c/buildasm/mul.asm.ejs rename to ports/c/buildasm/mul.asm.ejs diff --git a/c/buildasm/neg.asm.ejs b/ports/c/buildasm/neg.asm.ejs similarity index 100% rename from c/buildasm/neg.asm.ejs rename to ports/c/buildasm/neg.asm.ejs diff --git a/c/buildasm/old/buildfieldasm.js b/ports/c/buildasm/old/buildfieldasm.js similarity index 100% rename from c/buildasm/old/buildfieldasm.js rename to ports/c/buildasm/old/buildfieldasm.js diff --git a/c/buildasm/old/buildzqfield.js b/ports/c/buildasm/old/buildzqfield.js similarity index 100% rename from c/buildasm/old/buildzqfield.js rename to ports/c/buildasm/old/buildzqfield.js diff --git a/c/buildasm/old/buildzqfieldtester.js b/ports/c/buildasm/old/buildzqfieldtester.js similarity index 100% rename from c/buildasm/old/buildzqfieldtester.js rename to ports/c/buildasm/old/buildzqfieldtester.js diff --git a/c/buildasm/old/fr.asm.ejs.old b/ports/c/buildasm/old/fr.asm.ejs.old similarity index 100% rename from c/buildasm/old/fr.asm.ejs.old rename to ports/c/buildasm/old/fr.asm.ejs.old diff --git a/c/buildasm/old/mul.asm.ejs b/ports/c/buildasm/old/mul.asm.ejs similarity index 100% rename from c/buildasm/old/mul.asm.ejs rename to ports/c/buildasm/old/mul.asm.ejs diff --git a/c/buildasm/sub.asm.ejs b/ports/c/buildasm/sub.asm.ejs similarity index 100% rename from c/buildasm/sub.asm.ejs rename to ports/c/buildasm/sub.asm.ejs diff --git a/ports/c/buildasm/tester b/ports/c/buildasm/tester new file mode 100755 index 0000000..e782f2a Binary files /dev/null and b/ports/c/buildasm/tester differ diff --git a/c/buildasm/tester.cpp b/ports/c/buildasm/tester.cpp similarity index 100% rename from c/buildasm/tester.cpp rename to ports/c/buildasm/tester.cpp diff --git a/ports/c/buildasm/tester.dSYM/Contents/Info.plist b/ports/c/buildasm/tester.dSYM/Contents/Info.plist new file mode 100644 index 0000000..c78a483 --- /dev/null +++ b/ports/c/buildasm/tester.dSYM/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.tester + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/ports/c/buildasm/tester.dSYM/Contents/Resources/DWARF/tester b/ports/c/buildasm/tester.dSYM/Contents/Resources/DWARF/tester new file mode 100644 index 0000000..8404f1b Binary files /dev/null and b/ports/c/buildasm/tester.dSYM/Contents/Resources/DWARF/tester differ diff --git a/c/buildasm/utils.asm.ejs b/ports/c/buildasm/utils.asm.ejs similarity index 99% rename from c/buildasm/utils.asm.ejs rename to ports/c/buildasm/utils.asm.ejs index 24a59d0..6925c52 100644 --- a/c/buildasm/utils.asm.ejs +++ b/ports/c/buildasm/utils.asm.ejs @@ -70,4 +70,3 @@ return ( pop rdi`); } %> - diff --git a/src/builder_c.js b/ports/c/builder.js similarity index 97% rename from src/builder_c.js rename to ports/c/builder.js index f95133f..f328ec8 100644 --- a/src/builder_c.js +++ b/ports/c/builder.js @@ -1,10 +1,10 @@ -const streamFromMultiArray = require("./stream_from_multiarray"); +const streamFromMultiArray = require("../../src/streamfromarray_txt.js"); const bigInt = require("big-integer"); -const utils = require("./utils"); +const utils = require("../../src/utils"); const assert = require("assert"); function ref2src(c) { - if (c[0] == "R") { + if ((c[0] == "R")||(c[0] == "RI")) { return c[1]; } else if (c[0] == "V") { return c[1].toString(); @@ -94,6 +94,9 @@ class CodeBuilderC { this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr}); } + log(val) { + this.ops.push({op: "LOG", val}); + } concat(cb) { this.ops.push(...cb.ops); @@ -211,6 +214,8 @@ class CodeBuilderC { code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`); } else if (o.op == "CHECKCONSTRAINT") { code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`); + } else if (o.op == "LOG") { + code.push(`ctx->log(${ref2src(o.val)});`); } }); } @@ -342,6 +347,8 @@ class BuilderC { this.constants = []; this.functions = []; this.components = []; + this.usedConstants = {}; + } setHeader(header) { @@ -362,7 +369,11 @@ class BuilderC { } addConstant(c) { + c = bigInt(c); + const cS = c.toString(); + if (this.usedConstants[cS]) return this.usedConstants[cS]; this.constants.push(c); + this.usedConstants[cS] = this.constants.length - 1; return this.constants.length - 1; } diff --git a/c/calcwit.cpp b/ports/c/calcwit.cpp similarity index 97% rename from c/calcwit.cpp rename to ports/c/calcwit.cpp index 9a9d17a..fc3bcda 100644 --- a/c/calcwit.cpp +++ b/ports/c/calcwit.cpp @@ -63,6 +63,8 @@ void Circom_CalcWit::reset() { for (int i=0; iNComponents; i++) { inputSignalsToTrigger[i] = circuit->components[i].inputSignals; + } + for (int i=0; iNComponents; i++) { if (inputSignalsToTrigger[i] == 0) triggerComponent(i); } } @@ -171,6 +173,9 @@ void Circom_CalcWit::setSignal(int currentComponentIdx, int cIdx, int sIdx, PFrE if (inputSignalsToTrigger[cIdx]>0) { inputSignalsToTrigger[cIdx]--; if (inputSignalsToTrigger[cIdx] == 0) triggerComponent(cIdx); + } else { + fprintf(stderr, "Input signals does not match with map: %d\n", sIdx); + assert(false); } } diff --git a/c/calcwit.h b/ports/c/calcwit.h similarity index 100% rename from c/calcwit.h rename to ports/c/calcwit.h diff --git a/c/circom.h b/ports/c/circom.h similarity index 100% rename from c/circom.h rename to ports/c/circom.h diff --git a/c/fr.c b/ports/c/fr.c similarity index 100% rename from c/fr.c rename to ports/c/fr.c diff --git a/c/fr.h b/ports/c/fr.h similarity index 100% rename from c/fr.h rename to ports/c/fr.h diff --git a/c/fr.o b/ports/c/fr.o similarity index 100% rename from c/fr.o rename to ports/c/fr.o diff --git a/c/main.cpp b/ports/c/main.cpp similarity index 100% rename from c/main.cpp rename to ports/c/main.cpp diff --git a/c/mainjson.cpp b/ports/c/mainjson.cpp similarity index 100% rename from c/mainjson.cpp rename to ports/c/mainjson.cpp diff --git a/src/c_tester.js b/ports/c/tester.js similarity index 95% rename from src/c_tester.js rename to ports/c/tester.js index 0cc1b46..17e4725 100644 --- a/src/c_tester.js +++ b/ports/c/tester.js @@ -4,15 +4,15 @@ const assert = chai.assert; const fs = require("fs"); var tmp = require("tmp-promise"); const path = require("path"); -const compiler = require("./compiler"); +const compiler = require("../../src/compiler"); const util = require("util"); const exec = util.promisify(require("child_process").exec); -const stringifyBigInts = require("./utils").stringifyBigInts; -const unstringifyBigInts = require("./utils").unstringifyBigInts; +const stringifyBigInts = require("../../src/utils").stringifyBigInts; +const unstringifyBigInts = require("../../src/utils").unstringifyBigInts; const bigInt = require("big-integer"); -const utils = require("./utils"); -const loadR1cs = require("./r1csfile").loadR1cs; +const utils = require("../../src/utils"); +const loadR1cs = require("../../src/r1csfile").loadR1cs; const ZqField = require("fflib").ZqField; module.exports = c_tester; diff --git a/c/utils.cpp b/ports/c/utils.cpp similarity index 100% rename from c/utils.cpp rename to ports/c/utils.cpp diff --git a/c/utils.h b/ports/c/utils.h similarity index 100% rename from c/utils.h rename to ports/c/utils.h diff --git a/c/zqfield.cpp b/ports/c/zqfield.cpp similarity index 100% rename from c/zqfield.cpp rename to ports/c/zqfield.cpp diff --git a/c/zqfield.h b/ports/c/zqfield.h similarity index 100% rename from c/zqfield.h rename to ports/c/zqfield.h diff --git a/ports/wasm/build_runtime.js b/ports/wasm/build_runtime.js new file mode 100644 index 0000000..16cb709 --- /dev/null +++ b/ports/wasm/build_runtime.js @@ -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"); + +}; diff --git a/ports/wasm/builder.js b/ports/wasm/builder.js new file mode 100644 index 0000000..5cf32c0 --- /dev/null +++ b/ports/wasm/builder.js @@ -0,0 +1,1003 @@ +const streamFromArrayTxt = require("../../src/streamfromarray_txt"); +const streamFromArrayBin = require("../../src/streamfromarray_bin"); +const bigInt = require("big-integer"); +const assert = require("assert"); +const ModuleBuilder = require("wasmbuilder").ModuleBuilder; +const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat; +const buildRuntime = require("./build_runtime"); + + +const errs = require("./errs"); + +function hexToBytesR(hex) { + for (var bytes = [], c = hex.length-2; c >=0; c -= 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + + +function intToBytes32(v) { + return [ v &0xFF, (v>>8) & 0xFF, (v>>16) & 0xFF, (v>>24) & 0xFF ]; +} + + +class CodeBuilderWasm { + constructor(fnBuilder) { + this.fnBuilder = fnBuilder; + this.ops = []; + } + + addComment(comment) { + this.ops.push({op: "COMMENT", comment}); + } + + addBlock(block) { + this.ops.push({op: "BLOCK", block}); + } + + calcOffset(dLabel, offsets) { + this.ops.push({op: "CALCOFFSETS", dLabel, offsets}); + } + + assign(dLabel, src, sOffset) { + this.ops.push({op: "ASSIGN", dLabel, src, sOffset}); + } + + getSubComponentOffset(dLabel, component, hash, hashLabel) { + this.ops.push({op: "GETSUBCOMPONENTOFFSET", dLabel, component, hash, hashLabel}); + } + + getSubComponentSizes(dLabel, component, hash, hashLabel) { + this.ops.push({op: "GETSUBCOMPONENTSIZES", dLabel, component, hash, hashLabel}); + } + + getSignalOffset(dLabel, component, hash, hashLabel) { + this.ops.push({op: "GETSIGNALOFFSET", dLabel, component, hash, hashLabel}); + } + + getSignalSizes(dLabel, component, hash, hashLabel) { + this.ops.push({op: "GETSIGNALSIZES", dLabel, component, hash, hashLabel}); + } + + setSignal(component, signal, value) { + this.ops.push({op: "SETSIGNAL", component, signal, value}); + } + + getSignal(dLabel, component, signal) { + this.ops.push({op: "GETSIGNAL", dLabel, component, signal}); + } + + copyN(dLabel, offset, src, n) { + this.ops.push({op: "COPYN", dLabel, offset, src, n}); + } + + copyNRet(src, n) { + this.ops.push({op: "COPYNRET", src, n}); + } + + fieldOp(dLabel, fOp, params) { + this.ops.push({op: "FOP", dLabel, fOp, params}); + } + + ret() { + this.ops.push({op: "RET"}); + } + + addLoop(condLabel, body) { + this.ops.push({op: "LOOP", condLabel, body}); + } + + addIf(condLabel, thenCode, elseCode) { + this.ops.push({op: "IF", condLabel, thenCode, elseCode}); + } + + fnCall(fnName, retLabel, params) { + this.ops.push({op: "FNCALL", fnName, retLabel, params}); + } + + checkConstraint(a, b, strErr) { + this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr}); + } + + + concat(cb) { + this.ops.push(...cb.ops); + } + + hasCode() { + for (let i=0; i { + if ((o[0][0] == "V") && (o[1][0]== "V")) { + rN += o[0][1]*o[1][1]; + return; + } + let f=[]; + if (o[0][0] == "V") { + f = c.i32_const(o[0][1]); + } else if (o[0][0] == "RI") { + f = c.i32_load(this.fnBuilder._getPtr(c, o[0][1])); + } else if (o[0][0] == "R") { + f = c.call("Fr_toInt", this.fnBuilder._getPtr(c, o[0][1])); + } else { + assert(false); + } + if (o[1][0] == "V") { + if (o[1][1]==0) return; + if (o[1][1]>1) { + f = c.i32_mul(f, c.i32_const(o[1][1])); + } + } else if (o[1][0] == "RS") { + f = c.i32_mul( + f, + c.i32_load( + c.i32_add( + c.i32_load(this.fnBuilder._getPtr(c, o[1][1])), + c.i32_const(o[1][2]*4) + ) + ) + ); + } else { + assert(false); + } + if (S!=null) { + S = c.i32_add( S, f); + } else { + S = f; + } + }); + if (rN>0) { + if (S!=null) { + S = c.i32_add( S, c.i32_const(rN)); + } else { + S = c.i32_const(rN); + } + } + return S; + } + + build(c) { + const code = []; + this.ops.forEach( (o) => { + if (o.op == "COMMENT") { + code.push( + c.comment(o.comment) + ); + // DO nothing + } else if (o.op == "BLOCK") { + code.push( + o.block.build(c) + ); + } else if (o.op == "CALCOFFSETS") { + code.push( + c.i32_store( + this.fnBuilder._getPtr(c, o.dLabel), + this._buildOffset(c, o.offsets) + ) + ); + } else if (o.op == "ASSIGN") { + code.push( + c.i32_store( + this.fnBuilder._getPtr(c, o.dLabel), + c.i32_add( + this.fnBuilder._deRefFr(c, o.src), + c.i32_mul( + this.fnBuilder._deRefInt(c, o.sOffset), + c.i32_const(this.fnBuilder.builder.sizeFr) + ) + ) + ) + ); + } else if (o.op == "GETSUBCOMPONENTOFFSET") { + code.push( + c.call( + "getSubComponentOffset", + this.fnBuilder._getPtr(c, o.dLabel), + this.fnBuilder._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + } else if (o.op == "GETSUBCOMPONENTSIZES") { + code.push( + c.call( + "getSubComponentSizes", + this.fnBuilder._getPtr(c, o.dLabel), + this.fnBuilder._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + } else if (o.op == "GETSIGNALOFFSET") { + code.push( + c.call( + "getSignalOffset", + this.fnBuilder._getPtr(c, o.dLabel), + this.fnBuilder._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + } else if (o.op == "GETSIGNALSIZES") { + code.push( + c.call( + "getSignalSizes", + this.fnBuilder._getPtr(c, o.dLabel), + this.fnBuilder._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + } else if (o.op == "SETSIGNAL") { + code.push( + c.call( + "setSignal", + c.getLocal("cIdx"), + this.fnBuilder._deRefInt(c, o.component), + this.fnBuilder._deRefInt(c, o.signal), + this.fnBuilder._deRefFr(c, o.value) + ) + ); + } else if (o.op == "GETSIGNAL") { + code.push( + c.call( + "getSignal", + c.getLocal("cIdx"), + this.fnBuilder._getPtr(c, o.dLabel), + this.fnBuilder._deRefInt(c, o.component), + this.fnBuilder._deRefInt(c, o.signal) + ) + ); + } else if (o.op == "COPYN") { + code.push( + c.call( + "Fr_copyn", + c.i32_add( + this.fnBuilder._getPtr(c, o.dLabel), + c.i32_mul( + this.fnBuilder._deRefInt(c, o.offset), + c.i32_const(this.fnBuilder.builder.sizeFr) + ) + ), + this.fnBuilder._deRefFr(c, o.src), + c.i32_const(o.n) + ) + ); + } else if (o.op == "COPYNRET") { + code.push( + c.call( + "Fr_copyn", + c.getLocal("pRet"), + this.fnBuilder._deRefFr(c, o.src), + c.i32_const(o.n) + ) + ); + } else if (o.op == "RET") { + code.push(this.fnBuilder._freeStack(c)); + code.push(c.ret([])); + } else if (o.op == "FOP") { + let params = []; + for (let i=0; i { + code.push( + c.call( + "Fr_copy", + this._getPtr(c, o.dLabel, o.offset), + this._getPtrConstant(c, o.idConstant) + ) + ); + }); + this.initializedSignalOffset.forEach( (o) => { + code.push( + c.call( + "getSignalOffset", + this._getPtr(c, o.dLabel, o.offset), + this._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + }); + this.initializedSignalSizes.forEach( (o) => { + code.push( + c.call( + "getSignalSizes", + this._getPtr(c, o.dLabel, o.offset), + this._deRefInt(c, o.component), + c.i64_const("0x" + o.hash) + ) + ); + }); + return code; + } + + _buildFooter(c) { + return this._freeStack(c); + } + + newCodeBuilder() { + return new CodeBuilderWasm(this); + } + + setBody(body) { + this.body = body; + } + + build(module) { + + + const f = module.addFunction(this.name, this.instanceDef); + + if (this.type=="COMPONENT") { + f.addParam("cIdx", "i32"); + } else if (this.type=="FUNCTION") { + f.addParam("pRet", "i32"); + for (let i=0;i 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 ${v}`); + } + return lines.join("\n"); + } + + async checkConstraints(witness) { + const self = this; + if (!self.constraints) await self.loadConstraints(); + for (let i=0; i> 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>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> 2) + 2 + i] = a.shiftRight(i*32).and(self.mask32); + } + } + } +} + + + diff --git a/src/build.js b/src/build.js index a4edfe4..3dd9bbb 100644 --- a/src/build.js +++ b/src/build.js @@ -34,7 +34,6 @@ function build(ctx) { ctx.codes_sizes = []; ctx.definedSizes = {}; ctx.addSizes = addSizes; - ctx.constantsMap = {}; ctx.addConstant = addConstant; ctx.addConstant(bigInt.zero); ctx.addConstant(bigInt.one); @@ -287,12 +286,7 @@ function addSizes(_sizes) { } function addConstant(c) { - c = bigInt(c); - const s = c.toString(); - if (typeof (this.constantsMap[s]) !== "undefined") return this.constantsMap[s]; - const cIdx = this.builder.addConstant(c); - this.constantsMap[s] = cIdx; - return cIdx; + return this.builder.addConstant(c); } function buildFunction(name, paramValues) { @@ -320,7 +314,7 @@ function buildFunction(name, paramValues) { ctx.scopes = [{}]; ctx.refs = []; ctx.conditionalCode = false; - ctx.fnBuilder = ctx.builder.newFunctionBuilder(`${name}_${h}`, instanceDef); + ctx.fnBuilder = ctx.builder.newFunctionBuilder(`${name}_${h}`, instanceDef, ctx.functions[name].params); ctx.codeBuilder = ctx.fnBuilder.newCodeBuilder(); ctx.uniqueNames = Object.assign({},ctx.globalNames); ctx.returnValue = null; diff --git a/src/builder_wasm.js b/src/builder_wasm.js deleted file mode 100644 index 9c2b2e1..0000000 --- a/src/builder_wasm.js +++ /dev/null @@ -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; diff --git a/src/buildsyms.js b/src/buildsyms.js new file mode 100644 index 0000000..688f1b2 --- /dev/null +++ b/src/buildsyms.js @@ -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 { 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 options.cSourceWriteStream.on("finish", fulfill)); } - if (options.wasmWriteStream) { + if ((options.wasmWriteStream)||(options.watWriteStream)) { ctx.builder = new BuilderWasm(); build(ctx); - const rdStream = ctx.builder.build(); - rdStream.pipe(options.wasmWriteStream); + if (options.wasmWriteStream) { + const rdStream = ctx.builder.build("wasm"); + rdStream.pipe(options.wasmWriteStream); + } + if (options.watWriteStream) { + const rdStream = ctx.builder.build("wat"); + rdStream.pipe(options.watWriteStream); + } // await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill)); } @@ -109,7 +116,10 @@ async function compile(srcFile, options) { } if (options.symWriteStream) { - buildSyms(ctx, options.symWriteStream); + const rdStream = buildSyms(ctx); + rdStream.pipe(options.symWriteStream); + + // await new Promise(fulfill => options.symWriteStream.on("finish", fulfill)); } // const def = buildCircuitDef(ctx, mainCode); @@ -504,6 +514,8 @@ function buildConstraints(ctx) { return res; } */ + +/* function buildSyms(ctx, strm) { let nSyms; @@ -543,5 +555,5 @@ function buildSyms(ctx, strm) { } - +*/ diff --git a/src/gencode.js b/src/gencode.js index 894bef9..98a070d 100644 --- a/src/gencode.js +++ b/src/gencode.js @@ -754,7 +754,13 @@ function toRefA_Int1(ctx, ast, aRef) { const a = ctx.refs[aRef]; if (a.sizes[0] != 1) return ctx.throwError(ast, "Expected only one element"); if (a.used) { - return ["R", a.label]; + if (a.type == "INT") { + return ["RI", a.label]; + } else if (a.type == "BIGINT") { + return ["R", a.label]; + } else { + assert(false); + } } else { return ["V", a.value[0]]; } @@ -818,9 +824,7 @@ function genArray(ctx, ast) { function genFunctionCall(ctx, ast) { if (ast.name == "log") { const vRef = gen(ctx, ast.params[0]); - const val = ctx.refs[vRef]; - instantiateRef(ctx, vRef, val.value); - ctx.code+=`ctx->log(${val.label});`; + ctx.codeBuilder.log(toRefA_Fr1(ctx, ast.params[0], vRef)); return vRef; } const params = []; diff --git a/src/r1csfile.js b/src/r1csfile.js index b81d620..8ea335d 100644 --- a/src/r1csfile.js +++ b/src/r1csfile.js @@ -235,7 +235,7 @@ async function buildR1cs(ctx, fileName) { } for (let i=0; i= 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; +}; diff --git a/src/stream_from_multiarray.js b/src/streamfromarray_txt.js similarity index 93% rename from src/stream_from_multiarray.js rename to src/streamfromarray_txt.js index a0cdf0b..4624f0a 100644 --- a/src/stream_from_multiarray.js +++ b/src/streamfromarray_txt.js @@ -1,7 +1,7 @@ const Readable = require("stream").Readable; -module.exports = function streamFromMultiarray(ma) { +module.exports = function streamFromArrayTxt(ma) { const rs = Readable(); let curIndex = getFirstIdx(ma); @@ -10,7 +10,7 @@ module.exports = function streamFromMultiarray(ma) { let res; res = objFromIdx(ma, curIndex); curIndex = nextIdx(curIndex); - if (res!=null) { + if (res!==null) { rs.push(res + "\n"); } else { rs.push(null); diff --git a/test/basiccases.js b/test/basiccases.js index f7351ec..68d5ee1 100644 --- a/test/basiccases.js +++ b/test/basiccases.js @@ -2,9 +2,11 @@ const path = require("path"); const bigInt = require("big-integer"); const c_tester = require("../index.js").c_tester; +const wasm_tester = require("../index.js").wasm_tester; const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const basicCases = require("./basiccases.json"); function normalize(o) { if ((typeof(o) == "bigint") || o.isZero !== undefined) { @@ -31,11 +33,14 @@ function normalize(o) { } -async function doTest(circuit, testVectors) { - const cir = await c_tester(path.join(__dirname, "circuits", circuit)); +async function doTest(tester, circuit, testVectors) { + const cir = await tester(path.join(__dirname, "circuits", circuit)); for (let i=0; i { + await doTest(c_tester, basicCases[i].circuit, basicCases[i].tv); + }); + } +*/ - 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}], - ] - ); - }); + for (let i=16; i<17; i++) { + it("wasm " + basicCases[i].name, async () => { + await doTest(wasm_tester, basicCases[i].circuit, basicCases[i].tv); + }); + } }); diff --git a/test/basiccases.js.old b/test/basiccases.js.old new file mode 100644 index 0000000..f7351ec --- /dev/null +++ b/test/basiccases.js.old @@ -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 { + 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}], + ] + ); + }); + +}); diff --git a/test/basiccases.json b/test/basiccases.json new file mode 100644 index 0000000..a18e7a2 --- /dev/null +++ b/test/basiccases.json @@ -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}] + ] + } +] diff --git a/test/circuits/arrays.circom b/test/circuits/arrays.circom index 30ca5ce..df1e31c 100644 --- a/test/circuits/arrays.circom +++ b/test/circuits/arrays.circom @@ -31,9 +31,11 @@ template Main() { out[0] === in+c[0]; out[1] <-- d[1]+c[1]; + // out[1] === (in+in)+3+c[1]; out[1] === 2*in+3+c[1]; out[2] <-- d[2]+c[2]; + // out[2] === (in+in+in+in+in+in)+12+c[2]; out[2] === 6*in+12+c[2]; } diff --git a/test/circuits/inc.json b/test/circuits/inc.json deleted file mode 100644 index 04cb7f5..0000000 --- a/test/circuits/inc.json +++ /dev/null @@ -1 +0,0 @@ -{"x": "3"} diff --git a/test/fieldasm.js b/test/fieldasm.js index ff69977..5900abd 100644 --- a/test/fieldasm.js +++ b/test/fieldasm.js @@ -1,4 +1,4 @@ -const tester = require("../c/buildasm/buildzqfieldtester.js"); +const tester = require("../ports/c/buildasm/buildzqfieldtester.js"); const ZqField = require("fflib").ZqField; @@ -17,7 +17,6 @@ describe("field asm test", function () { const tv = buildTestVector2(bn128r, "add"); await tester(bn128r, tv); }); - it("secp256k1q add", async () => { const tv = buildTestVector2(secp256k1q, "add"); await tester(secp256k1q, tv); @@ -267,7 +266,6 @@ describe("field asm test", function () { const tv = buildTestVector1(mnt6753q, "square"); await tester(mnt6753q, tv); }); - }); function buildTestVector2(p, op) {