Wasm generation finished

This commit is contained in:
Jordi Baylina
2020-03-16 20:37:08 +01:00
parent 8f63d18ff4
commit ef899e618b
27 changed files with 2617 additions and 374 deletions

View File

@@ -116,14 +116,14 @@ add_l1ms2m:
;;;;;;;;
add_s1l2:
bt rcx, 62 ; check if montgomery first
bt rcx, 62 ; check if montgomery second
jc add_s1l2m
add_s1l2n:
<%= global.setTypeDest("0x80"); %>
<%= addS1L2(); %>
add_s1l2m:
bt rax, 62 ; check if montgomery second
bt rax, 62 ; check if montgomery first
jc add_s1ml2m
add_s1nl2m:
<%= global.setTypeDest("0xC0"); %>

View File

@@ -1,3 +1,24 @@
<% function binOpSubQIfBigger() { %>
<% const subQ = global.tmpLabel() %>
<% const done = global.tmpLabel() %>
; Compare with q
<% for (let i=0; i<n64; i++) { %>
mov rax, [rdi + <%= (n64-i)*8 %>]
cmp rax, [q + <%= (n64-i-1)*8 %>]
jc <%=done%> ; q is bigget so done.
jnz <%=subQ%> ; q is lower
<% } %>
; If equal substract q
<%=subQ%>:
<% for (let i=0; i<n64; i++) { %>
mov rax, [q + <%=i*8%>]
<%= i==0 ? "sub" : "sbb" %> [rdi + <%=i*8 + 8 %>], rax
<% } %>
<%=done%>:
<% } %>
<% function binOpS1S2(op) { %>
cmp r8d, 0
<% const s1s2_solveNeg = global.tmpLabel() %>
@@ -35,6 +56,7 @@
<% } %>
mov [rdi + <%= (i*8)+8 %> ], rax
<% } %>
<% binOpSubQIfBigger() %>
ret
<%=s1l2_solveNeg%>:
@@ -59,6 +81,7 @@
<% } %>
mov [rdi + <%= (i*8)+8 %> ], rax;
<% } %>
<% binOpSubQIfBigger() %>
ret
<%=l1s2_solveNeg%>:
@@ -77,12 +100,11 @@
<% } %>
mov [rdi + <%= (i*8)+8 %> ], rax
<% } %>
<% binOpSubQIfBigger() %>
ret
<% } %>
<% function binOp(op) { %>
;;;;;;;;;;;;;;;;;;;;;;
; b<%= op %>
@@ -212,6 +234,7 @@ bnot_l1n:
<% } %>
mov [rdi + <%= i*8 + 8 %>], rax
<% } %>
<% binOpSubQIfBigger() %>
ret

File diff suppressed because it is too large Load Diff

View File

@@ -49,5 +49,5 @@ q dq <%= constantElement(q) %>
half dq <%= constantElement(q.shiftRight(1)) %>
R2 dq <%= constantElement(bigInt.one.shiftLeft(n64*64*2).mod(q)) %>
R3 dq <%= constantElement(bigInt.one.shiftLeft(n64*64*3).mod(q)) %>
lboMask dq 0x<%= bigInt("8000000000000000",16).shiftRight(n64*64 - q.bitLength()).minus(bigInt.one).toString(16) %>
lboMask dq 0x<%= bigInt("10000000000000000",16).shiftRight(n64*64 - q.bitLength()).minus(bigInt.one).toString(16) %>

View File

@@ -19,6 +19,7 @@ void Fr_toMpz(mpz_t r, PFrElement pE) {
mpz_add(r, r, q);
}
} else {
Fr_toNormal(pE);
mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)pE->longVal);
}
}
@@ -42,7 +43,7 @@ void Fr_init() {
mpz_init_set_ui(one, 1);
nBits = mpz_sizeinbase (q, 2);
mpz_init(mask);
mpz_mul_2exp(mask, one, nBits-1);
mpz_mul_2exp(mask, one, nBits);
mpz_sub(mask, mask, one);
}
@@ -118,11 +119,19 @@ void Fr_shl(PFrElement r, PFrElement a, PFrElement b) {
Fr_toMpz(ma, a);
Fr_toMpz(mb, b);
if (mpz_cmp_ui(mb, nBits) >= 0) {
mpz_set(mr, zero);
} else {
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_mul_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
if (mpz_cmp(mr, q) >= 0) {
mpz_sub(mr, mr, q);
}
} else {
mpz_sub(mb, q, mb);
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_tdiv_q_2exp(mr, ma, mpz_get_ui(mb));
} else {
mpz_set(mr, zero);
}
}
Fr_fromMpz(r, mr);
}
@@ -137,11 +146,19 @@ void Fr_shr(PFrElement r, PFrElement a, PFrElement b) {
Fr_toMpz(ma, a);
Fr_toMpz(mb, b);
if (mpz_cmp_ui(mb, nBits) >= 0) {
mpz_set(mr, zero);
} else {
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_tdiv_q_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
} else {
mpz_sub(mb, q, mb);
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_mul_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
if (mpz_cmp(mr, q) >= 0) {
mpz_sub(mr, mr, q);
}
} else {
mpz_set(mr, zero);
}
}
Fr_fromMpz(r, mr);
}

View File

@@ -19,6 +19,7 @@ void <%=name%>_toMpz(mpz_t r, P<%=name%>Element pE) {
mpz_add(r, r, q);
}
} else {
<%=name%>_toNormal(pE);
mpz_import(r, <%=name%>_N64, -1, 8, -1, 0, (const void *)pE->longVal);
}
}
@@ -42,7 +43,7 @@ void <%=name%>_init() {
mpz_init_set_ui(one, 1);
nBits = mpz_sizeinbase (q, 2);
mpz_init(mask);
mpz_mul_2exp(mask, one, nBits-1);
mpz_mul_2exp(mask, one, nBits);
mpz_sub(mask, mask, one);
}
@@ -118,11 +119,19 @@ void <%=name%>_shl(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b
<%=name%>_toMpz(ma, a);
<%=name%>_toMpz(mb, b);
if (mpz_cmp_ui(mb, nBits) >= 0) {
mpz_set(mr, zero);
} else {
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_mul_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
if (mpz_cmp(mr, q) >= 0) {
mpz_sub(mr, mr, q);
}
} else {
mpz_sub(mb, q, mb);
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_tdiv_q_2exp(mr, ma, mpz_get_ui(mb));
} else {
mpz_set(mr, zero);
}
}
<%=name%>_fromMpz(r, mr);
}
@@ -137,11 +146,19 @@ void <%=name%>_shr(P<%=name%>Element r, P<%=name%>Element a, P<%=name%>Element b
<%=name%>_toMpz(ma, a);
<%=name%>_toMpz(mb, b);
if (mpz_cmp_ui(mb, nBits) >= 0) {
mpz_set(mr, zero);
} else {
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_tdiv_q_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
} else {
mpz_sub(mb, q, mb);
if (mpz_cmp_ui(mb, nBits) < 0) {
mpz_mul_2exp(mr, ma, mpz_get_ui(mb));
mpz_and(mr, mr, mask);
if (mpz_cmp(mr, q) >= 0) {
mpz_sub(mr, mr, q);
}
} else {
mpz_set(mr, zero);
}
}
<%=name%>_fromMpz(r, mr);
}

Binary file not shown.

View File

@@ -245,23 +245,25 @@ montgomeryTemplate("rawFromMontgomery", function(i, r0, r1, r2) {
;;;;;;;;;;;;;;;;;;;;
<%=name%>_toMontgomery:
mov rax, [rdi]
bts rax, 62 ; check if montgomery
bt rax, 62 ; check if montgomery
jc toMontgomery_doNothing
bts rax, 63
bt rax, 63
jc toMontgomeryLong
toMontgomeryShort:
mov [rdi], rax
add rdi, 8
push rsi
push rdx
lea rsi, [R2]
movsx rdx, eax
cmp rdx, 0
js negMontgomeryShort
posMontgomeryShort:
call rawMontgomeryMul1
pop rdx
pop rsi
sub rdi, 8
<%= global.setTypeDest("0x40"); %>
ret
negMontgomeryShort:
@@ -269,8 +271,10 @@ negMontgomeryShort:
call rawMontgomeryMul1
mov rsi, rdi
call rawNegL
pop rdx
pop rsi
sub rdi, 8
<%= global.setTypeDest("0x40"); %>
ret
@@ -283,6 +287,8 @@ toMontgomeryLong:
call rawMontgomeryMul
pop rsi
sub rdi, 8
<%= global.setTypeDest("0xC0"); %>
toMontgomery_doNothing:
ret
@@ -297,16 +303,16 @@ toMontgomery_doNothing:
;;;;;;;;;;;;;;;;;;;;
<%=name%>_toNormal:
mov rax, [rdi]
btc rax, 62 ; check if montgomery
bt rax, 62 ; check if montgomery
jnc toNormal_doNothing
bt rax, 63 ; if short, it means it's converted
jnc toNormal_doNothing
toNormalLong:
mov [rdi], rax
add rdi, 8
call rawFromMontgomery
sub rdi, 8
<%= global.setTypeDest("0x80"); %>
toNormal_doNothing:
ret
@@ -331,6 +337,7 @@ toLongNormal_fromMontgomery:
add rdi, 8
call rawFromMontgomery
sub rdi, 8
<%= global.setTypeDest("0x80"); %>
ret
toLongNormal_fromShort:
@@ -338,5 +345,6 @@ toLongNormal_fromShort:
movsx rsi, eax
call rawCopyS2L
mov rsi, r8 ; recover rsi
<%= global.setTypeDest("0x80"); %>
ret

Binary file not shown.

View File

@@ -56,6 +56,8 @@ void fillMap() {
addFunction("land", (FuncAny)Fr_land, 2);
addFunction("lor", (FuncAny)Fr_lor, 2);
addFunction("lnot", (FuncAny)Fr_lnot, 1);
addFunction("shl", (FuncAny)Fr_shl, 2);
addFunction("shr", (FuncAny)Fr_shr, 2);
}
u_int64_t readInt(std::string &s) {

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.tester</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -1,8 +1,8 @@
<% global.setTypeDest = function (t) {
return (
` mov r11b, ${t}
shl r11, 56
mov [rdi], r11`);
shl r11d, 24
mov [rdi+4], r11d`);
} %>

View File

@@ -184,7 +184,7 @@ int main(int argc, char *argv[]) {
ctx->join();
printf("Finished!\n");
// printf("Finished!\n");
std::string outfilename = argv[2];

View File

@@ -47,7 +47,7 @@ async function c_tester(circomFile, _options) {
` ${path.join(dir.path, baseName + ".cpp")} ` +
` -o ${path.join(dir.path, baseName)}` +
` -I ${cdir}` +
" -lgmp -std=c++11 -DSANITY_CHECK"
" -lgmp -std=c++11 -DSANITY_CHECK -g"
);
// console.log(dir.path);
@@ -70,10 +70,13 @@ class CTester {
path.join(this.dir.path, "in.json"),
JSON.stringify(stringifyBigInts(input), null, 1)
);
await exec(`${path.join(this.dir.path, this.baseName)}` +
const r = await exec(`${path.join(this.dir.path, this.baseName)}` +
` ${path.join(this.dir.path, "in.json")}` +
` ${path.join(this.dir.path, "out.json")}`
);
if (r.stdout) {
console.log(r.stdout);
}
const resStr = await fs.promises.readFile(
path.join(this.dir.path, "out.json")
);

View File

@@ -545,15 +545,15 @@ module.exports = function buildRuntime(module, builder) {
f.addCode(
c.call(
"Fr_eq",
c.getLocal(c.i32_const(pTmp)),
c.i32_const(pTmp),
c.getLocal("pA"),
c.getLocal("pB")
),
c.if (
c.eqz(
c.i32_eqz(
c.call(
"Fr_isTrue",
c.getLocal(c.i32_const(pTmp)),
c.i32_const(pTmp),
)
),
c.call(
@@ -658,21 +658,6 @@ module.exports = function buildRuntime(module, builder) {
);
}
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");
@@ -703,6 +688,9 @@ module.exports = function buildRuntime(module, builder) {
fErr4.addParam("param3", "i32");
fErr4.addParam("param4", "i32");
const fLog = module.addIimportFunction("log", "runtime");
fLog.addParam("code", "i32");
buildWasmFf(module, "Fr", builder.header.P);
builder.pSignals=module.alloc(builder.header.NSignals*builder.sizeFr);
@@ -734,7 +722,7 @@ module.exports = function buildRuntime(module, builder) {
buildGetPWitness();
buildGetPRawPrime();
buildFrToInt();
// buildFrToInt();
module.exportFunction("init");
module.exportFunction("getNVars");

View File

@@ -104,6 +104,10 @@ class CodeBuilderWasm {
this.ops.push(...cb.ops);
}
log(val) {
this.ops.push({op: "LOG", val});
}
hasCode() {
for (let i=0; i<this.ops.length; i++) {
if (this.ops[i].op != "COMMENT") return true;
@@ -111,6 +115,7 @@ class CodeBuilderWasm {
return false;
}
_buildOffset(c, offsets) {
let rN=0;
let S = null;
@@ -671,7 +676,7 @@ class FunctionBuilderWasm {
}
class BuilderWasm {
constructor() {
constructor(sanityCheck) {
this.hashMaps={};
this.componentEntriesTables={};
this.sizes ={};
@@ -679,6 +684,7 @@ class BuilderWasm {
this.usedConstants = {};
this.functions = [];
this.components = [];
this.sanityCheck = sanityCheck;
this.TYPE_SIGNAL = 1;
this.TYPE_COMPONENT = 2;
@@ -989,6 +995,8 @@ class BuilderWasm {
this._buildMapIsInput(module);
this._buildWit2Sig(module);
this._buildCircuitVar(module);
module.setMemory(2000);
if (outType == "wasm") {
return streamFromArrayBin(module.build());
} else if (outType == "wat") {

View File

@@ -33,6 +33,7 @@ async function wasm_tester(circomFile, _options) {
options.wasmWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".wasm"));
options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
options.sanityCheck = true;
const promisesArr = [];
promisesArr.push(new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill)));

View File

@@ -17,33 +17,55 @@ module.exports.fromBuffer = async function(code) {
const memory = new WebAssembly.Memory({initial:20000});
const wasmModule = await WebAssembly.compile(code);
let wc;
const instance = await WebAssembly.instantiate(wasmModule, {
env: {
"memory": memory
},
runtime: {
err: function(code, pstr) {
console.log("ERROR", code, p2str(pstr));
const errStr=p2str(pstr);
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err1: function(code, pstr, a) {
console.log("ERROR: ", code, p2str(pstr), a);
const errStr=p2str(pstr)+ " " + a;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err2: function(code, pstr, a, b) {
console.log("ERROR: ", code, p2str(pstr), a, b);
const errStr=p2str(pstr)+ " " + a + " " + b;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err3: function(code, pstr, a, b, c) {
console.log("ERROR: ", code, p2str(pstr), a, b, c);
const errStr=p2str(pstr)+ " " + a + " " + b + " " + c;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err4: function(code, pstr, a,b,c,d) {
console.log("ERROR: ", code, p2str(pstr), a, b, c, d);
const errStr=p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " +p2str(d);
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
log: function(a) {
console.log(wc.getFr(a).toString());
},
}
});
return new WitnessCalculator(memory, instance);
wc = new WitnessCalculator(memory, instance);
return wc;
function p2str(p) {
return "TODO"+p;
const i8 = new Uint8Array(memory.buffer);
const bytes = [];
for (let i=0; i8[p+i]>0; i++) bytes.push(i8[p+i]);
return String.fromCharCode.apply(null, bytes);
}
};
@@ -120,30 +142,31 @@ class WitnessCalculator {
}
getFr(p) {
const self = this;
const idx = (p>>2);
if (this.i32[idx + 1] & 0x80000000) {
if (self.i32[idx + 1] & 0x80000000) {
let res= bigInt(0);
for (let i=this.n32-1; i>=0; i--) {
for (let i=self.n32-1; i>=0; i--) {
res = res.shiftLeft(32);
res = res.add(bigInt(this.i32[idx+2+i]));
res = res.add(bigInt(self.i32[idx+2+i]));
}
if (this.i32[idx + 1] & 0x40000000) {
if (self.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)) );
if (self.i32[idx] & 0x80000000) {
return self.prime.add( bigInt(self.i32[idx]).minus(bigInt(0x100000000)) );
} else {
return bigInt(this.i32[idx]);
return bigInt(self.i32[idx]);
}
}
function fromMontgomery(n) {
return n.times(this.RInv).mod(this.prime);
return n.times(self.RInv).mod(self.prime);
}
}