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