function setupWasm(fileName, nameSpace, setupFct) {
console.log('setupWasm ' + fileName)
let mod = {}
fetch(fileName)
.then(response => response.arrayBuffer())
.then(buffer => new Uint8Array(buffer))
.then(binary => {
mod['wasmBinary'] = binary
mod['onRuntimeInitialized'] = function() {
setupFct(mod, nameSpace)
console.log('setupWasm end')
}
Module(mod)
})
return mod
}
const MCLBN_CURVE_FP254BNB = 0
const MCLBN_CURVE_FP382_1 = 1
const MCLBN_CURVE_FP382_2 = 2
const MCLBN_FP_UNIT_SIZE = 6
const BLS_ID_SIZE = MCLBN_FP_UNIT_SIZE * 8
const BLS_SECRETKEY_SIZE = BLS_ID_SIZE
const BLS_PUBLICKEY_SIZE = BLS_ID_SIZE * 3 * 2
const BLS_SIGNATURE_SIZE = BLS_ID_SIZE * 3
function define_bls_extra_functions(mod) {
const ptrToStr = function(pos, n) {
let s = ''
for (let i = 0; i < n; i++) {
s += String.fromCharCode(mod.HEAP8[pos + i])
}
return s
}
const Uint8ArrayToMem = function(pos, buf) {
for (let i = 0; i < buf.length; i++) {
mod.HEAP8[pos + i] = buf[i]
}
}
const AsciiStrToMem = function(pos, s) {
for (let i = 0; i < s.length; i++) {
mod.HEAP8[pos + i] = s.charCodeAt(i)
}
}
const wrap_outputString = function(func, doesReturnString = true) {
return function(x, ioMode = 0) {
let maxBufSize = 2048
let stack = mod.Runtime.stackSave()
let pos = mod.Runtime.stackAlloc(maxBufSize)
let n = func(pos, maxBufSize, x, ioMode)
if (n < 0) {
throw('err gen_str:' + x)
}
if (doesReturnString) {
let s = ptrToStr(pos, n)
mod.Runtime.stackRestore(stack)
return s
} else {
let a = new Uint8Array(n)
for (let i = 0; i < n; i++) {
a[i] = mod.HEAP8[pos + i]
}
mod.Runtime.stackRestore(stack)
return a
}
}
}
const wrap_outputArray = function(func) {
return wrap_outputString(func, false)
}
const wrap_input0 = function(func, returnValue = false) {
return function(buf, ioMode = 0) {
let stack = mod.Runtime.stackSave()
let pos = mod.Runtime.stackAlloc(buf.length)
if (typeof(buf) == "string") {
AsciiStrToMem(pos, buf)
} else {
Uint8ArrayToMem(pos, buf)
}
let r = func(pos, buf.length, ioMode)
mod.Runtime.stackRestore(stack)
if (returnValue) return r
if (r) throw('err wrap_input0 ' + buf)
}
}
const wrap_input1 = function(func, returnValue = false) {
return function(x1, buf, ioMode = 0) {
let stack = mod.Runtime.stackSave()
let pos = mod.Runtime.stackAlloc(buf.length)
if (typeof(buf) == "string") {
AsciiStrToMem(pos, buf)
} else {
Uint8ArrayToMem(pos, buf)
}
let r = func(x1, pos, buf.length, ioMode)
mod.Runtime.stackRestore(stack)
if (returnValue) return r
if (r) throw('err wrap_input1 ' + buf)
}
}
const wrap_input2 = function(func, returnValue = false) {
return function(x1, x2, buf, ioMode = 0) {
let stack = mod.Runtime.stackSave()
let pos = mod.Runtime.stackAlloc(buf.length)
if (typeof(buf) == "string") {
AsciiStrToMem(pos, buf)
} else {
Uint8ArrayToMem(pos, buf)
}
let r = func(x1, x2, pos, buf.length, ioMode)
mod.Runtime.stackRestore(stack)
if (returnValue) return r
if (r) throw('err wrap_input2 ' + buf)
}
}
const wrap_keyShare = function(func, dataSize) {
return function(x, vec, id) {
let k = vec.length
let p = mod._malloc(dataSize * k)
for (let i = 0; i < k; i++) {
mod._memcpy(p + i * dataSize, vec[i], dataSize)
}
let r = func(x, p, k, id)
mod._free(p)
if (r) throw('keyShare ' + k)
}
}
const wrap_recover = function(func, dataSize, idDataSize) {
return function(x, vec, idVec) {
let n = vec.length
let p = mod._malloc(dataSize * n)
let q = mod._malloc(idDataSize * n)
for (let i = 0; i < n; i++) {
mod._memcpy(p + i * dataSize, vec[i], dataSize)
mod._memcpy(q + i * idDataSize, idVec[i], idDataSize)
}
let r = func(x, p, q, n)
mod._free(q)
mod._free(p)
if (r) throw('recover ' + n)
}
}
let crypto = window.crypto || window.msCrypto
let copyToUint32Array = function(a, pos) {
for (let i = 0; i < a.length; i++) {
a[i] = mod.HEAP32[pos / 4 + i]
}
}
let copyFromUint32Array = function(pos, a) {
for (let i = 0; i < a.length; i++) {
mod.HEAP32[pos / 4 + i] = a[i]
}
}
let callSetter = function(func, a, p1, p2) {
let pos = mod._malloc(a.length * 4)
func(pos, p1, p2) // p1, p2 may be undefined
copyToUint32Array(a, pos)
mod._free(pos)
}
let callGetter = function(func, a, p1, p2) {
let pos = mod._malloc(a.length * 4)
mod.HEAP32.set(a, pos / 4)
let s = func(pos, p1, p2)
mod._free(pos)
return s
}
let callModifier = function(func, a, p1, p2) {
let pos = mod._malloc(a.length * 4)
mod.HEAP32.set(a, pos / 4)
func(pos, p1, p2) // p1, p2 may be undefined
copyToUint32Array(a, pos)
mod._free(pos)
}
///////////////////////////////////////////////////////////////
const FR_SIZE = MCLBN_FP_UNIT_SIZE * 8
const G1_SIZE = FR_SIZE * 3
const G2_SIZE = FR_SIZE * 3 * 2
const GT_SIZE = FR_SIZE * 12
mclBnFr_malloc = function() {
return mod._malloc(FR_SIZE)
}
mcl_free = function(x) {
mod._free(x)
}
mclBnFr_deserialize = wrap_input1(_mclBnFr_deserialize)
mclBnFr_setLittleEndian = wrap_input1(_mclBnFr_setLittleEndian)
mclBnFr_setStr = wrap_input1(_mclBnFr_setStr)
mclBnFr_getStr = wrap_outputString(_mclBnFr_getStr)
mclBnFr_setHashOf = wrap_input1(_mclBnFr_setHashOf)
///////////////////////////////////////////////////////////////
mclBnG1_malloc = function() {
return mod._malloc(G1_SIZE)
}
mclBnG1_setStr = wrap_input1(_mclBnG1_setStr)
mclBnG1_getStr = wrap_outputString(_mclBnG1_getStr)
mclBnG1_deserialize = wrap_input1(_mclBnG1_deserialize)
mclBnG1_serialize = wrap_outputArray(_mclBnG1_serialize)
mclBnG1_hashAndMapTo = wrap_input1(_mclBnG1_hashAndMapTo)
///////////////////////////////////////////////////////////////
mclBnG2_malloc = function() {
return mod._malloc(G2_SIZE)
}
mclBnG2_setStr = wrap_input1(_mclBnG2_setStr)
mclBnG2_getStr = wrap_outputString(_mclBnG2_getStr)
mclBnG2_deserialize = wrap_input1(_mclBnG2_deserialize)
mclBnG2_serialize = wrap_outputArray(_mclBnG2_serialize)
mclBnG2_hashAndMapTo = wrap_input1(_mclBnG2_hashAndMapTo)
///////////////////////////////////////////////////////////////
mclBnGT_malloc = function() {
return mod._malloc(GT_SIZE)
}
mclBnGT_deserialize = wrap_input1(_mclBnGT_deserialize)
mclBnGT_serialize = wrap_outputArray(_mclBnGT_serialize)
mclBnGT_setStr = wrap_input1(_mclBnGT_setStr)
mclBnGT_getStr = wrap_outputString(_mclBnGT_getStr)
///////////////////////////////////////////////////////////////
bls_free = mcl_free
blsId_malloc = mclBnFr_malloc
blsSecretKey_malloc = mclBnFr_malloc
blsPublicKey_malloc = mclBnG2_malloc
blsSignature_malloc = mclBnG1_malloc
blsInit = function(curveType) {
return _blsInit(curveType, MCLBN_FP_UNIT_SIZE)
}
blsGetCurveOrder = wrap_outputString(_blsGetCurveOrder)
blsGetFieldOrder = wrap_outputString(_blsGetFieldOrder)
blsIdSetDecStr = wrap_input1(_blsIdSetDecStr)
blsIdSetHexStr = wrap_input1(_blsIdSetHexStr)
blsIdGetDecStr = wrap_outputString(_blsIdGetDecStr)
blsIdGetHexStr = wrap_outputString(_blsIdGetHexStr)
blsSecretKeySetDecStr = wrap_input1(_blsSecretKeySetDecStr)
blsSecretKeySetHexStr = wrap_input1(_blsSecretKeySetHexStr)
blsSecretKeyGetDecStr = wrap_outputString(_blsSecretKeyGetDecStr)
blsSecretKeyGetHexStr = wrap_outputString(_blsSecretKeyGetHexStr)
blsIdSerialize = wrap_outputArray(_blsIdSerialize)
blsSecretKeySerialize = wrap_outputArray(_blsSecretKeySerialize)
blsPublicKeySerialize = wrap_outputArray(_blsPublicKeySerialize)
blsSignatureSerialize = wrap_outputArray(_blsSignatureSerialize)
blsIdDeserialize = wrap_input1(_blsIdDeserialize)
blsSecretKeyDeserialize = wrap_input1(_blsSecretKeyDeserialize)
blsPublicKeyDeserialize = wrap_input1(_blsPublicKeyDeserialize)
blsSignatureDeserialize = wrap_input1(_blsSignatureDeserialize)
blsSecretKeySetLittleEndian = wrap_input1(_blsSecretKeySetLittleEndian)
blsHashToSecretKey = wrap_input1(_blsHashToSecretKey)
blsSign = wrap_input2(_blsSign)
blsVerify = wrap_input2(_blsVerify, true)
blsSecretKeyShare = wrap_keyShare(_blsSecretKeyShare, BLS_SECRETKEY_SIZE)
blsPublicKeyShare = wrap_keyShare(_blsPublicKeyShare, BLS_PUBLICKEY_SIZE)
blsSecretKeyRecover = wrap_recover(_blsSecretKeyRecover, BLS_SECRETKEY_SIZE, BLS_ID_SIZE)
blsPublicKeyRecover = wrap_recover(_blsPublicKeyRecover, BLS_PUBLICKEY_SIZE, BLS_ID_SIZE)
blsSignatureRecover = wrap_recover(_blsSignatureRecover, BLS_SIGNATURE_SIZE, BLS_ID_SIZE)
/// BlsId
BlsId = function() {
this.a_ = new Uint32Array(BLS_ID_SIZE / 4)
}
BlsId.prototype.setInt = function(x) {
callSetter(blsIdSetInt, this.a_, x)
}
BlsId.prototype.setByCSPRNG = function() {
callSetter(blsSecretKeySetByCSPRNG, this.a_) // same type of BlsSecretKey
}
BlsId.prototype.setStr = function(s, base = 10) {
switch (base) {
case 10:
callSetter(blsIdSetDecStr, this.a_, s)
return
case 16:
callSetter(blsIdSetHexStr, this.a_, s)
return
default:
throw('BlsId.setStr:bad base:' + base)
}
}
BlsId.prototype.deserialize = function(s) {
callSetter(blsIdDeserialize, this.a_, s)
}
BlsId.prototype.getStr = function(base = 10) {
switch (base) {
case 10:
return callGetter(blsIdGetDecStr, this.a_)
case 16:
return callGetter(blsIdGetHexStr, this.a_)
default:
throw('BlsId.getStr:bad base:' + base)
}
}
BlsId.prototype.serialize = function() {
return callGetter(blsIdSerialize, this.a_)
}
/// BlsSecretKey
BlsSecretKey = function() {
this.a_ = new Uint32Array(BLS_SECRETKEY_SIZE / 4)
}
BlsSecretKey.prototype.setInt = function(x) {
callSetter(blsIdSetInt, this.a_, x) // same as Id
}
BlsSecretKey.prototype.deserialize = function(s) {
callSetter(blsSecretKeyDeserialize, this.a_, s)
}
BlsSecretKey.prototype.setLittleEndian = function(s) {
callSetter(blsSecretKeySetLittleEndian, this.a_, s)
}
BlsSecretKey.prototype.serialize = function() {
return callGetter(blsSecretKeySerialize, this.a_)
}
BlsSecretKey.prototype.setHashOf = function(s) {
callSetter(blsHashToSecretKey, this.a_, s)
}
BlsSecretKey.prototype.setByCSPRNG = function() {
let a = new Uint8Array(BLS_SECRETKEY_SIZE)
crypto.getRandomValues(a)
this.setLittleEndian(a)
// callSetter(blsSecretKeySetByCSPRNG, this.a_)
}
// return BlsPublicKey
BlsSecretKey.prototype.getPublicKey = function() {
let pub = new BlsPublicKey()
let stack = mod.Runtime.stackSave()
let secPos = mod.Runtime.stackAlloc(this.a_.length * 4)
let pubPos = mod.Runtime.stackAlloc(pub.a_.length * 4)
mod.HEAP32.set(this.a_, secPos / 4)
blsGetPublicKey(pubPos, secPos)
copyToUint32Array(pub.a_, pubPos)
mod.Runtime.stackRestore(stack)
return pub
}
/*
input
m : message (string or Uint8Array)
return
BlsSignature
*/
BlsSecretKey.prototype.sign = function(m) {
let sig = new BlsSignature()
let stack = mod.Runtime.stackSave()
let secPos = mod.Runtime.stackAlloc(this.a_.length * 4)
let sigPos = mod.Runtime.stackAlloc(sig.a_.length * 4)
mod.HEAP32.set(this.a_, secPos / 4)
blsSign(sigPos, secPos, m)
copyToUint32Array(sig.a_, sigPos)
mod.Runtime.stackRestore(stack)
return sig
}
/// BlsPublicKey
BlsPublicKey = function() {
this.a_ = new Uint32Array(BLS_PUBLICKEY_SIZE / 4)
}
BlsPublicKey.prototype.deserialize = function(s) {
callSetter(blsPublicKeyDeserialize, this.a_, s)
}
BlsPublicKey.prototype.serialize = function() {
return callGetter(blsPublicKeySerialize, this.a_)
}
BlsPublicKey.prototype.verify = function(sig, m) {
let stack = mod.Runtime.stackSave()
let pubPos = mod.Runtime.stackAlloc(this.a_.length * 4)
let sigPos = mod.Runtime.stackAlloc(sig.a_.length * 4)
mod.HEAP32.set(this.a_, pubPos / 4)
mod.HEAP32.set(sig.a_, sigPos / 4)
let r = blsVerify(sigPos, pubPos, m)
mod.Runtime.stackRestore(stack)
return r != 0
}
/// BlsSignature
BlsSignature = function() {
this.a_ = new Uint32Array(BLS_SIGNATURE_SIZE / 4)
}
BlsSignature.prototype.deserialize = function(s) {
callSetter(blsSignatureDeserialize, this.a_, s)
}
BlsSignature.prototype.serialize = function() {
return callGetter(blsSignatureSerialize, this.a_)
}
const share = function(func, a, size, vec, id) {
let stack = mod.Runtime.stackSave()
let pos = mod.Runtime.stackAlloc(a.length * 4)
let idPos = mod.Runtime.stackAlloc(id.a_.length * 4)
mod.HEAP32.set(a, pos / 4)
mod.HEAP32.set(id.a_, idPos / 4)
let vecPos = mod._malloc(size * vec.length)
for (let i = 0; i < vec.length; i++) {
copyFromUint32Array(vecPos + size * i, vec[i].a_)
}
func(pos, vecPos, vec.length, idPos)
mod._free(vecPos)
copyToUint32Array(a, pos)
mod.Runtime.stackRestore(stack)
}
/*
set shared BlsSecretKey by msk and id
input
msk : master secret key(array of BlsSecretKey)
id : BlsId
*/
BlsSecretKey.prototype.share = function(msk, id) {
share(_blsSecretKeyShare, this.a_, BLS_SECRETKEY_SIZE, msk, id)
}
BlsPublicKey.prototype.share = function(msk, id) {
share(_blsPublicKeyShare, this.a_, BLS_PUBLICKEY_SIZE, msk, id)
}
const recover = function(func, a, size, vec, idVec) {
let n = vec.length
if (n != idVec.length) throw('recover:bad length')
let stack = mod.Runtime.stackSave()
let secPos = mod.Runtime.stackAlloc(a.length * 4)
let vecPos = mod._malloc(size * n)
let idVecPos = mod._malloc(BLS_ID_SIZE * n)
for (let i = 0; i < n; i++) {
copyFromUint32Array(vecPos + size * i, vec[i].a_)
copyFromUint32Array(idVecPos + BLS_ID_SIZE * i, idVec[i].a_)
}
func(secPos, vecPos, idVecPos, n)
mod._free(idVecPos)
mod._free(vecPos)
copyToUint32Array(a, secPos)
mod.Runtime.stackRestore(stack)
}
/*
recover BlsSecretKey from (secVec, idVec)
secVec : array of BlsSecretKey
*/
BlsSecretKey.prototype.recover = function(secVec, idVec) {
recover(_blsSecretKeyRecover, this.a_, BLS_SECRETKEY_SIZE, secVec, idVec)
}
BlsPublicKey.prototype.recover = function(secVec, idVec) {
recover(_blsPublicKeyRecover, this.a_, BLS_PUBLICKEY_SIZE, secVec, idVec)
}
BlsSignature.prototype.recover = function(secVec, idVec) {
recover(_blsSignatureRecover, this.a_, BLS_SIGNATURE_SIZE, secVec, idVec)
}
}