diff --git a/lib/index.ts b/lib/index.ts index 783cccd50c..90999ed4b8 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -3,6 +3,7 @@ import { StateManager } from './state' import Common from 'ethereumjs-common' import Account from 'ethereumjs-account' import { default as runCode, RunCodeOpts, RunCodeCb } from './runCode' +import { default as runCall, RunCallOpts, RunCallCb } from './runCall' const promisify = require('util.promisify') const AsyncEventEmitter = require('async-eventemitter') const Blockchain = require('ethereumjs-blockchain') @@ -71,10 +72,13 @@ export default class VM extends AsyncEventEmitter { this.runJIT = require('./runJit.js').bind(this) this.runBlock = require('./runBlock.js').bind(this) this.runTx = require('./runTx.js').bind(this) - this.runCall = require('./runCall.js').bind(this) this.runBlockchain = require('./runBlockchain.js').bind(this) } + runCall (opts: RunCallOpts, cb: RunCallCb): void { + runCall.bind(this)(opts, cb) + } + runCode (opts: RunCodeOpts, cb: RunCodeCb): void { runCode.bind(this)(opts, cb) } diff --git a/lib/runCall.js b/lib/runCall.js deleted file mode 100644 index 518f4b61b5..0000000000 --- a/lib/runCall.js +++ /dev/null @@ -1,50 +0,0 @@ -const ethUtil = require('ethereumjs-util') -const Block = require('ethereumjs-block') -const BN = ethUtil.BN -const { StorageReader } = require('./state') -const TxContext = require('./evm/txContext').default -const Message = require('./evm/message').default -const Interpreter = require('./evm/interpreter').default - -/** - * runs a CALL operation - * @method vm.runCall - * @private - * @param opts - * @param opts.block {Block} - * @param opts.caller {Buffer} - * @param opts.code {Buffer} this is for CALLCODE where the code to load is different than the code from the to account. - * @param opts.data {Buffer} - * @param opts.gasLimit {Buffer | BN.js } - * @param opts.gasPrice {Buffer} - * @param opts.origin {Buffer} [] - * @param opts.to {Buffer} - * @param opts.value {Buffer} - * @param {Function} cb the callback - */ -module.exports = function (opts, cb) { - const block = opts.block || new Block() - const storageReader = opts.storageReader || new StorageReader(this.stateManager) - - const txContext = new TxContext(opts.gasPrice, opts.origin || opts.caller) - const message = new Message({ - caller: opts.caller, - gasLimit: opts.gasLimit ? new BN(opts.gasLimit) : new BN(0xffffff), - to: opts.to && opts.to.toString('hex') !== '' ? opts.to : undefined, - value: opts.value, - data: opts.data, - code: opts.code, - depth: opts.depth, - isCompiled: opts.compiled, - isStatic: opts.static, - salt: opts.salt, - // opts.suicides is kept for backward compatiblity with pre-EIP6 syntax - selfdestruct: opts.selfdestruct || opts.suicides, - delegatecall: opts.delegatecall - }) - - const interpreter = new Interpreter(this, txContext, block, storageReader) - interpreter.executeMessage(message) - .then((results) => cb(null, results)) - .catch((err) => cb(err, null)) -} diff --git a/lib/runCall.ts b/lib/runCall.ts new file mode 100644 index 0000000000..396abc280f --- /dev/null +++ b/lib/runCall.ts @@ -0,0 +1,73 @@ +import BN = require('bn.js') +import { zeros } from 'ethereumjs-util' +import VM from './index' +import { StorageReader } from './state' +import TxContext from './evm/txContext' +import Message from './evm/message' +import { default as Interpreter, InterpreterResult } from './evm/interpreter' +const Block = require('ethereumjs-block') + +export interface RunCallOpts { + block?: any + storageReader?: StorageReader + gasPrice?: Buffer + origin?: Buffer + caller?: Buffer + gasLimit?: Buffer + to?: Buffer + value?: Buffer + data?: Buffer + code?: Buffer + depth?: number + compiled?: boolean + static?: boolean + salt?: Buffer + selfdestruct?: {[k: string]: boolean} + delegatecall?: boolean +} + +export interface RunCallCb { + (err: Error | null, results: InterpreterResult | null): void +} + +/** + * runs a CALL operation + * @method vm.runCall + * @private + * @param opts + * @param opts.block {Block} + * @param opts.caller {Buffer} + * @param opts.code {Buffer} this is for CALLCODE where the code to load is different than the code from the to account. + * @param opts.data {Buffer} + * @param opts.gasLimit {Buffer | BN.js } + * @param opts.gasPrice {Buffer} + * @param opts.origin {Buffer} [] + * @param opts.to {Buffer} + * @param opts.value {Buffer} + * @param {Function} cb the callback + */ +export default function runCall (this: VM, opts: RunCallOpts, cb: RunCallCb): void { + const block = opts.block || new Block() + const storageReader = opts.storageReader || new StorageReader(this.stateManager) + + const txContext = new TxContext(opts.gasPrice || Buffer.alloc(0), opts.origin || opts.caller || zeros(32)) + const message = new Message({ + caller: opts.caller, + gasLimit: opts.gasLimit ? new BN(opts.gasLimit) : new BN(0xffffff), + to: opts.to && opts.to.toString('hex') !== '' ? opts.to : undefined, + value: opts.value, + data: opts.data, + code: opts.code, + depth: opts.depth || 0, + isCompiled: opts.compiled || false, + isStatic: opts.static || false, + salt: opts.salt || null, + selfdestruct: opts.selfdestruct || {}, + delegatecall: opts.delegatecall || false + }) + + const interpreter = new Interpreter(this, txContext, block, storageReader) + interpreter.executeMessage(message) + .then((results) => cb(null, results)) + .catch((err) => cb(err, null)) +}