mirror of
https://github.com/arnaucube/circomlib.git
synced 2026-02-06 18:56:43 +01:00
Merge other basic circuits here
This commit is contained in:
189
src/evmasm.js
Normal file
189
src/evmasm.js
Normal 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
37
src/mimc7.js
Normal 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
114
src/mimc_gencontract.js
Normal 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
18
src/printconstants.js
Normal 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
12
src/printcontract.js
Normal 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));
|
||||
Reference in New Issue
Block a user