Merge other basic circuits here

This commit is contained in:
Jordi Baylina
2018-12-06 17:32:49 +01:00
parent 2cab572c66
commit 2d43178c8d
83 changed files with 11727 additions and 201 deletions

189
src/evmasm.js Normal file
View File

@@ -0,0 +1,189 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Web3 = require("web3");
const assert = require("assert");
class Contract {
constructor() {
this.code = [];
this.labels = {};
this.pendingLabels = {};
}
createTxData() {
let C;
// Check all labels are defined
const pendingLabels = Object.keys(this.pendingLabels);
if (pendingLabels.length>0) {
throw new Error("Lables not defined: "+ pendingLabels.join(", "));
}
let setLoaderLength = 0;
let genLoadedLength = -1;
while (genLoadedLength!=setLoaderLength) {
setLoaderLength = genLoadedLength;
C = new module.exports();
C.codesize();
C.push(setLoaderLength);
C.push(0);
C.codecopy();
C.push(this.code.length);
C.push(0);
C.return();
genLoadedLength = C.code.length;
}
return Web3.utils.bytesToHex(C.code.concat(this.code));
}
stop() { this.code.push(0x00); }
add() { this.code.push(0x01); }
mul() { this.code.push(0x02); }
sub() { this.code.push(0x03); }
div() { this.code.push(0x04); }
sdiv() { this.code.push(0x05); }
mod() { this.code.push(0x06); }
smod() { this.code.push(0x07); }
addmod() { this.code.push(0x08); }
mulmod() { this.code.push(0x09); }
exp() { this.code.push(0x0a); }
signextend() { this.code.push(0x0b); }
lt() { this.code.push(0x10); }
gt() { this.code.push(0x11); }
slt() { this.code.push(0x12); }
sgt() { this.code.push(0x13); }
eq() { this.code.push(0x14); }
iszero() { this.code.push(0x15); }
and() { this.code.push(0x16); }
or() { this.code.push(0x17); }
shor() { this.code.push(0x18); }
not() { this.code.push(0x19); }
byte() { this.code.push(0x1a); }
keccak() { this.code.push(0x20); }
sha3() { this.code.push(0x20); } // alias
address() { this.code.push(0x30); }
balance() { this.code.push(0x31); }
origin() { this.code.push(0x32); }
caller() { this.code.push(0x33); }
callvalue() { this.code.push(0x34); }
calldataload() { this.code.push(0x35); }
calldatasize() { this.code.push(0x36); }
calldatacopy() { this.code.push(0x37); }
codesize() { this.code.push(0x38); }
codecopy() { this.code.push(0x39); }
gasprice() { this.code.push(0x3a); }
extcodesize() { this.code.push(0x3b); }
extcodecopy() { this.code.push(0x3c); }
returndatasize() { this.code.push(0x3d); }
returndatacopy() { this.code.push(0x3e); }
blockhash() { this.code.push(0x40); }
coinbase() { this.code.push(0x41); }
timestamp() { this.code.push(0x42); }
number() { this.code.push(0x43); }
difficulty() { this.code.push(0x44); }
gaslimit() { this.code.push(0x45); }
pop() { this.code.push(0x50); }
mload() { this.code.push(0x51); }
mstore() { this.code.push(0x52); }
mstore8() { this.code.push(0x53); }
sload() { this.code.push(0x54); }
sstore() { this.code.push(0x55); }
_pushLabel(label) {
if (typeof this.labels[label] != "undefined") {
this.push(this.labels[label]);
} else {
this.pendingLabels[label] = this.pendingLabels[label] || [];
this.pendingLabels[label].push(this.code.length);
this.push("0x000000");
}
}
_fillLabel(label) {
if (!this.pendingLabels[label]) return;
let dst = this.labels[label];
const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF];
this.pendingLabels[label].forEach((p) => {
for (let i=0; i<3; i++) {
this.code[p+i+1] = dst3[i];
}
});
delete this.pendingLabels[label];
}
jmp(label) {
this._pushLabel(label);
this.code.push(0x56);
}
jmpi(label) {
this._pushLabel(label);
this.code.push(0x57);
}
pc() { this.code.push(0x58); }
msize() { this.code.push(0x59); }
gas() { this.code.push(0x5a); }
label(name) {
assert(typeof this.labels[name] == "undefined", "Label already defined");
this.labels[name] = this.code.length;
this.code.push(0x5b);
this._fillLabel(name);
}
push(data) {
const d = Web3.utils.hexToBytes(Web3.utils.toHex(data));
assert(d.length>0);
assert(d.length<=32);
this.code = this.code.concat([0x5F + d.length], d);
}
dup(n) {
assert(n>=0);
assert(n<16);
this.code.push(0x80 + n);
}
swap(n) {
assert(n>=1);
assert(n<=16);
this.code.push(0x8f + n);
}
log0() { this.code.push(0xa0); }
log1() { this.code.push(0xa1); }
log2() { this.code.push(0xa2); }
log3() { this.code.push(0xa3); }
log4() { this.code.push(0xa4); }
create() { this.code.push(0xf0); }
call() { this.code.push(0xf1); }
callcode() { this.code.push(0xf2); }
return() { this.code.push(0xf3); }
delegatecall() { this.code.push(0xf4); }
staticcall() { this.code.push(0xfa); }
revert() { this.code.push(0xfd); }
invalid() { this.code.push(0xfe); }
selfdestruct() { this.code.push(0xff); }
}
module.exports = Contract;

37
src/mimc7.js Normal file
View File

@@ -0,0 +1,37 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Web3 = require("web3");
const F = bn128.Fr;
module.exports.hash = MiMC7Hash;
module.exports.getConstants = getConstants;
const SEED = "iden3_mimc";
function getConstants(seed, nRounds) {
const cts = new Array(nRounds);
let c = Web3.utils.keccak256(SEED);
for (let i=1; i<nRounds; i++) {
c = Web3.utils.keccak256(c);
const n1 = Web3.utils.toBN(c).mod(Web3.utils.toBN(F.q.toString()));
cts[i] = Web3.utils.padLeft(Web3.utils.toHex(n1), 64);
}
cts[0] = "0x0000000000000000000000000000000000000000000000000000000000000000";
return cts;
}
function MiMC7Hash(_x_in, _k, nRounds) {
const x_in = bigInt(_x_in);
const k = bigInt(_k);
const cts = getConstants(SEED, nRounds);
let r;
for (let i=0; i<nRounds; i++) {
const c = bigInt(Web3.utils.toBN(cts[i]).toString());
let t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
let t2 = F.square(t);
let t4 = F.square(t2);
r = F.mul(F.mul(t4, t2), t);
}
return F.affine(F.add(r, k));
}

114
src/mimc_gencontract.js Normal file
View File

@@ -0,0 +1,114 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Web3 = require("web3");
const Contract = require("./evmasm");
function createCode(seed, n) {
let ci = Web3.utils.keccak256(seed);
const C = new Contract();
C.push(0x44);
C.push("0x00");
C.push("0x00");
C.calldatacopy();
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push("0x00");
C.mload();
C.div();
C.push("0xd15ca109"); // MiMCpe7(uint256,uint256)
// C.push("0x8c42199e"); // MiMCpe7(uint256,uint256,uint256)
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
C.push("0x24");
C.mload(); // k q
C.dup(1); // q k q
C.dup(0); // q q k q
C.push("0x04");
C.mload(); // x q q k q
C.dup(3); // k x q q k q
C.addmod(); // t=x+k q k q
C.dup(1); // q t q k q
C.dup(0); // q q t q k q
C.dup(2); // t q q t q k q
C.dup(0); // t t q q t q k q
C.mulmod(); // a=t^2 q t q k q
C.dup(1); // q a q t q k q
C.dup(1); // a q a q t q k q
C.dup(0); // a a q a q t q k q
C.mulmod(); // b=t^4 a q t q k q
C.mulmod(); // c=t^6 t q k q
C.mulmod(); // r=t^7 k q
for (let i=0; i<n-1; i++) {
ci = Web3.utils.keccak256(ci);
C.dup(2); // q r k q
C.dup(0); // q q r k q
C.dup(0); // q q q r k q
C.swap(3); // r q q q k q
C.push(ci); // c r q q k q
C.addmod(); // s=c+r q q k q
C.dup(3); // k s q q k q
C.addmod(); // t=s+k q k q
C.dup(1); // q t q k q
C.dup(0); // q q t q k q
C.dup(2); // t q q t q k q
C.dup(0); // t t q q t q k q
C.mulmod(); // a=t^2 q t q k q
C.dup(1); // q a q t q k q
C.dup(1); // a q a q t q k q
C.dup(0); // a a q a q t q k q
C.mulmod(); // b=t^4 a q t q k q
C.mulmod(); // c=t^6 t q k q
C.mulmod(); // r=t^7 k q
}
C.addmod(); // res=t^7+k
C.push("0x00");
C.mstore(); // Save it to pos 0;
C.push("0x20");
C.push("0x00");
C.return();
return C.createTxData();
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "in_x",
"type": "uint256"
},
{
"name": "in_k",
"type": "uint256"
}
],
"name": "MiMCpe7",
"outputs": [
{
"name": "out_x",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

18
src/printconstants.js Normal file
View File

@@ -0,0 +1,18 @@
const mimc = require("./mimc7");
const SEED = "iden3_mimc";
let nRounds;
if (typeof process.argv[2] != "undefined") {
nRounds = parseInt(process.argv[2]);
} else {
nRounds = 256;
}
const cts = mimc.getConstants(SEED, nRounds);
for (let i=0; i<nRounds; i++) {
let S = cts[i];
if (i<nRounds-1) S=S+",";
console.log(S);
}

12
src/printcontract.js Normal file
View File

@@ -0,0 +1,12 @@
const mimcGenContract = require("./mimc_gencontract");
const SEED = "iden3_mimc";
let nRounds;
if (typeof process.argv[2] != "undefined") {
nRounds = parseInt(process.argv[2]);
} else {
nRounds = 91;
}
console.log(mimcGenContract.createCode(SEED, nRounds));