arnaucube
arnaucube/circomlibPublic Self-hosted repository
circomlib/src/evmasm.js
src/evmasm.jsRaw
  1// Copyright (c) 2018 Jordi Baylina
  2// License: LGPL-3.0+
  3//
  4
  5
  6const Web3Utils = require("web3-utils");
  7
  8class Contract {
  9    constructor() {
 10        this.code = [];
 11        this.labels = {};
 12        this.pendingLabels = {};
 13    }
 14
 15    createTxData() {
 16        let C;
 17
 18        // Check all labels are defined
 19        const pendingLabels = Object.keys(this.pendingLabels);
 20        if (pendingLabels.length>0) {
 21            throw new Error("Lables not defined: "+ pendingLabels.join(", "));
 22        }
 23
 24        let setLoaderLength = 0;
 25        let genLoadedLength = -1;
 26
 27        while  (genLoadedLength!=setLoaderLength) {
 28            setLoaderLength = genLoadedLength;
 29            C = new module.exports();
 30            C.codesize();
 31            C.push(setLoaderLength);
 32            C.push(0);
 33            C.codecopy();
 34
 35            C.push(this.code.length);
 36            C.push(0);
 37            C.return();
 38            genLoadedLength = C.code.length;
 39        }
 40
 41        return Web3Utils.bytesToHex(C.code.concat(this.code));
 42    }
 43
 44    stop() { this.code.push(0x00); }
 45    add()  { this.code.push(0x01); }
 46    mul()  { this.code.push(0x02); }
 47    sub()  { this.code.push(0x03); }
 48    div()  { this.code.push(0x04); }
 49    sdiv() { this.code.push(0x05); }
 50    mod()  { this.code.push(0x06); }
 51    smod()  { this.code.push(0x07); }
 52    addmod()  { this.code.push(0x08); }
 53    mulmod()  { this.code.push(0x09); }
 54    exp()  { this.code.push(0x0a); }
 55    signextend()  { this.code.push(0x0b); }
 56
 57    lt()   { this.code.push(0x10); }
 58    gt()   { this.code.push(0x11); }
 59    slt()  { this.code.push(0x12); }
 60    sgt()  { this.code.push(0x13); }
 61    eq()   { this.code.push(0x14); }
 62    iszero()  { this.code.push(0x15); }
 63    and()  { this.code.push(0x16); }
 64    or()  { this.code.push(0x17); }
 65    shor()  { this.code.push(0x18); }
 66    not()  { this.code.push(0x19); }
 67    byte()  { this.code.push(0x1a); }
 68
 69    keccak() { this.code.push(0x20); }
 70    sha3() { this.code.push(0x20); }   // alias
 71
 72    address()  { this.code.push(0x30); }
 73    balance()  { this.code.push(0x31); }
 74    origin()  { this.code.push(0x32); }
 75    caller()  { this.code.push(0x33); }
 76    callvalue()  { this.code.push(0x34); }
 77    calldataload()  { this.code.push(0x35); }
 78    calldatasize()  { this.code.push(0x36); }
 79    calldatacopy()  { this.code.push(0x37); }
 80    codesize()  { this.code.push(0x38); }
 81    codecopy()  { this.code.push(0x39); }
 82    gasprice()  { this.code.push(0x3a); }
 83    extcodesize()  { this.code.push(0x3b); }
 84    extcodecopy()  { this.code.push(0x3c); }
 85    returndatasize()  { this.code.push(0x3d); }
 86    returndatacopy()  { this.code.push(0x3e); }
 87
 88    blockhash()  { this.code.push(0x40); }
 89    coinbase()  { this.code.push(0x41); }
 90    timestamp()  { this.code.push(0x42); }
 91    number()  { this.code.push(0x43); }
 92    difficulty()  { this.code.push(0x44); }
 93    gaslimit()  { this.code.push(0x45); }
 94
 95    pop()  { this.code.push(0x50); }
 96    mload()  { this.code.push(0x51); }
 97    mstore()  { this.code.push(0x52); }
 98    mstore8()  { this.code.push(0x53); }
 99    sload()  { this.code.push(0x54); }
100    sstore()  { this.code.push(0x55); }
101
102    _pushLabel(label) {
103        if (typeof this.labels[label] != "undefined") {
104            this.push(this.labels[label]);
105        } else {
106            this.pendingLabels[label] = this.pendingLabels[label] || [];
107            this.pendingLabels[label].push(this.code.length);
108            this.push("0x000000");
109        }
110    }
111
112    _fillLabel(label) {
113        if (!this.pendingLabels[label]) return;
114
115        let dst = this.labels[label];
116
117        const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF];
118
119        this.pendingLabels[label].forEach((p) => {
120            for (let i=0; i<3; i++) {
121                this.code[p+i+1] = dst3[i];
122            }
123        });
124
125        delete this.pendingLabels[label];
126    }
127
128
129    jmp(label)  {
130        if (typeof label !== "undefined") {
131            this._pushLabel(label);
132        }
133        this.code.push(0x56);
134    }
135
136    jmpi(label)  {
137        if (typeof label !== "undefined") {
138            this._pushLabel(label);
139        }
140        this.code.push(0x57);
141    }
142
143    pc()  { this.code.push(0x58); }
144    msize()  { this.code.push(0x59); }
145    gas()  { this.code.push(0x5a); }
146    label(name)  {
147        if (typeof this.labels[name] != "undefined") {
148            throw new Error("Label already defined");
149        }
150        this.labels[name] = this.code.length;
151        this.code.push(0x5b);
152
153        this._fillLabel(name);
154    }
155
156    push(data) {
157        if (typeof data === "number") {
158            let isNeg;
159            if (data<0) {
160                isNeg = true;
161                data = -data;
162            }
163            data = data.toString(16);
164            if (data.length % 2 == 1) data = "0" + data;
165            data = "0x" + data;
166            if (isNeg) data = "-"+data;
167        }
168        const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
169        if (d.length == 0 || d.length > 32) {
170            throw new Error("Assertion failed");
171        }
172        this.code = this.code.concat([0x5F + d.length], d);
173    }
174
175    dup(n) {
176        if (n < 0 || n >= 16) {
177            throw new Error("Assertion failed");
178        }
179        this.code.push(0x80 + n);
180    }
181
182    swap(n) {
183        if (n < 1 || n > 16) {
184            throw new Error("Assertion failed");
185        }
186        this.code.push(0x8f + n);
187    }
188
189    log0()  { this.code.push(0xa0); }
190    log1()  { this.code.push(0xa1); }
191    log2()  { this.code.push(0xa2); }
192    log3()  { this.code.push(0xa3); }
193    log4()  { this.code.push(0xa4); }
194
195    create()  { this.code.push(0xf0); }
196    call()  { this.code.push(0xf1); }
197    callcode()  { this.code.push(0xf2); }
198    return()  { this.code.push(0xf3); }
199    delegatecall()  { this.code.push(0xf4); }
200
201    staticcall()  { this.code.push(0xfa); }
202    revert()  { this.code.push(0xfd); }
203    invalid()  { this.code.push(0xfe); }
204    selfdestruct()  { this.code.push(0xff); }
205}
206
207module.exports = Contract;
208