mirror of
https://github.com/tornadocash/circomlibjs.git
synced 2024-12-12 12:47:09 +01:00
209 lines
5.8 KiB
JavaScript
209 lines
5.8 KiB
JavaScript
|
// Copyright (c) 2018 Jordi Baylina
|
||
|
// License: LGPL-3.0+
|
||
|
//
|
||
|
|
||
|
|
||
|
const Web3Utils = require("web3-utils");
|
||
|
|
||
|
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 Web3Utils.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) {
|
||
|
if (typeof label !== "undefined") {
|
||
|
this._pushLabel(label);
|
||
|
}
|
||
|
this.code.push(0x56);
|
||
|
}
|
||
|
|
||
|
jmpi(label) {
|
||
|
if (typeof label !== "undefined") {
|
||
|
this._pushLabel(label);
|
||
|
}
|
||
|
this.code.push(0x57);
|
||
|
}
|
||
|
|
||
|
pc() { this.code.push(0x58); }
|
||
|
msize() { this.code.push(0x59); }
|
||
|
gas() { this.code.push(0x5a); }
|
||
|
label(name) {
|
||
|
if (typeof this.labels[name] != "undefined") {
|
||
|
throw new Error("Label already defined");
|
||
|
}
|
||
|
this.labels[name] = this.code.length;
|
||
|
this.code.push(0x5b);
|
||
|
|
||
|
this._fillLabel(name);
|
||
|
}
|
||
|
|
||
|
push(data) {
|
||
|
if (typeof data === "number") {
|
||
|
let isNeg;
|
||
|
if (data<0) {
|
||
|
isNeg = true;
|
||
|
data = -data;
|
||
|
}
|
||
|
data = data.toString(16);
|
||
|
if (data.length % 2 == 1) data = "0" + data;
|
||
|
data = "0x" + data;
|
||
|
if (isNeg) data = "-"+data;
|
||
|
}
|
||
|
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
|
||
|
if (d.length == 0 || d.length > 32) {
|
||
|
throw new Error("Assertion failed");
|
||
|
}
|
||
|
this.code = this.code.concat([0x5F + d.length], d);
|
||
|
}
|
||
|
|
||
|
dup(n) {
|
||
|
if (n < 0 || n >= 16) {
|
||
|
throw new Error("Assertion failed");
|
||
|
}
|
||
|
this.code.push(0x80 + n);
|
||
|
}
|
||
|
|
||
|
swap(n) {
|
||
|
if (n < 1 || n > 16) {
|
||
|
throw new Error("Assertion failed");
|
||
|
}
|
||
|
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;
|
||
|
|