Skip to content

Commit

Permalink
evm: promisify async opFns (#491)
Browse files Browse the repository at this point in the history
  • Loading branch information
s1na authored Apr 5, 2019
1 parent ca3374a commit ed5b1a9
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 283 deletions.
109 changes: 28 additions & 81 deletions lib/evm/eei.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const promisify = require('util.promisify')
const BN = require('bn.js')
const { VmError, ERROR } = require('../exceptions')
const PStateManager = require('../state/promisified')
Expand Down Expand Up @@ -34,21 +35,17 @@ module.exports = class EEI {
* Returns balance of the given account.
* @param {BN} address - Address of account
*/
getExternalBalance (address, cb) {
async getExternalBalance (address) {
address = addressToBuffer(address)

// shortcut if current account
if (address.toString('hex') === this._env.address.toString('hex')) {
return cb(null, new BN(this._env.contract.balance))
return new BN(this._env.contract.balance)
}

// otherwise load account then return balance
this._env.stateManager.getAccount(address, (err, account) => {
if (err) {
return cb(err, null)
}
cb(null, new BN(account.balance))
})
const account = await this._state.getAccount(address)
return new BN(account.balance)
}

/**
Expand Down Expand Up @@ -111,26 +108,22 @@ module.exports = class EEI {
/**
* Get size of an account’s code.
* @param {BN} address - Address of account
* @param {function} cb
*/
getExternalCodeSize (address, cb) {
async getExternalCodeSize (address) {
address = addressToBuffer(address)
this._env.stateManager.getContractCode(address, (err, code) => {
if (err) return cb(err)
cb(null, new BN(code.length))
})
const code = await this._state.getContractCode(address)
return new BN(code.length)
}

/**
* Returns code of an account.
* @param {BN} address - Address of account
* @param {function} cb
*/
getExternalCode (address, cb) {
async getExternalCode (address) {
if (!Buffer.isBuffer(address)) {
address = addressToBuffer(address)
}
this._env.stateManager.getContractCode(address, cb)
return this._state.getContractCode(address)
}

/**
Expand Down Expand Up @@ -214,38 +207,30 @@ module.exports = class EEI {
/**
* Returns Gets the hash of one of the 256 most recent complete blocks.
* @param {BN} - Number of block
* @param {function} cb
*/
getBlockHash (number, cb) {
this._env.blockchain.getBlock(number, (err, block) => {
if (err) return cb(err)
const blockHash = new BN(block.hash())
cb(null, blockHash)
})
async getBlockHash (number) {
const block = await promisify(this._env.blockchain.getBlock).bind(this._env.blockchain)(number)
return new BN(block.hash())
}

/**
* Store 256-bit a value in memory to persistent storage.
* @param {Buffer} key
* @param {Buffer} value
*/
storageStore (key, value, cb) {
this._state.putContractStorage(this._env.address, key, value)
.then(() => this._state.getAccount(this._env.address))
.then((account) => {
this._env.contract = account
cb(null)
})
.catch(cb)
async storageStore (key, value) {
await this._state.putContractStorage(this._env.address, key, value)
const account = await this._state.getAccount(this._env.address)
this._env.contract = account
}

/**
* Loads a 256-bit value to memory from persistent storage.
* @param {Buffer} key - Storage key
* @returns {Buffer}
*/
storageLoad (key, cb) {
this._env.stateManager.getContractStorage(this._env.address, key, cb)
async storageLoad (key) {
return this._state.getContractStorage(this._env.address, key)
}

/**
Expand Down Expand Up @@ -280,8 +265,8 @@ module.exports = class EEI {
* execution will be aborted immediately.
* @param {Buffer} toAddress - Beneficiary address
*/
selfDestruct (toAddress, cb) {
this._selfDestruct(toAddress).then(() => cb(null)).catch(cb)
async selfDestruct (toAddress) {
return this._selfDestruct(toAddress)
}

async _selfDestruct (toAddress) {
Expand Down Expand Up @@ -343,15 +328,8 @@ module.exports = class EEI {
* @param {Buffer} address
* @param {BN} value
* @param {Buffer} data
* @param {Function} cb
*/
call (gasLimit, address, value, data, cb) {
this._call(gasLimit, address, value, data)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
}

async _call (gasLimit, address, value, data) {
async call (gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.address,
gasLimit: gasLimit,
Expand All @@ -371,15 +349,8 @@ module.exports = class EEI {
* @param {Buffer} address
* @param {BN} value
* @param {Buffer} data
* @param {Function} cb
*/
callCode (gasLimit, address, value, data, cb) {
this._callCode(gasLimit, address, value, data)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
}

async _callCode (gasLimit, address, value, data) {
async callCode (gasLimit, address, value, data) {
let { compiled, code } = await this._getCode(address)

const msg = new Message({
Expand All @@ -405,15 +376,8 @@ module.exports = class EEI {
* @param {Buffer} address
* @param {BN} value
* @param {Buffer} data
* @param {Function} cb
*/
callStatic (gasLimit, address, value, data, cb) {
this._callStatic(gasLimit, address, value, data)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
}

async _callStatic (gasLimit, address, value, data) {
async callStatic (gasLimit, address, value, data) {
const msg = new Message({
caller: this._env.address,
gasLimit: gasLimit,
Expand All @@ -434,15 +398,8 @@ module.exports = class EEI {
* @param {Buffer} address
* @param {BN} value
* @param {Buffer} data
* @param {Function} cb
*/
callDelegate (gasLimit, address, value, data, cb) {
this._callDelegate(gasLimit, address, value, data)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
}

async _callDelegate (gasLimit, address, value, data) {
async callDelegate (gasLimit, address, value, data) {
let { compiled, code } = await this._getCode(address)

const msg = new Message({
Expand Down Expand Up @@ -522,15 +479,8 @@ module.exports = class EEI {
* @param {BN} gasLimit
* @param {BN} value
* @param {Buffer} data
* @param {Function} cb
*/
create (gasLimit, value, data, cb) {
this._create(gasLimit, value, data)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
}

async _create (gasLimit, value, data, salt = null) {
async create (gasLimit, value, data, salt = null) {
const selfdestruct = Object.assign({}, this._env.selfdestruct)
const msg = new Message({
caller: this._env.address,
Expand Down Expand Up @@ -599,12 +549,9 @@ module.exports = class EEI {
* @param {BN} value
* @param {Buffer} data
* @param {Buffer} salt
* @param {Function} cb
*/
create2 (gasLimit, value, data, salt, cb) {
this._create(gasLimit, value, data, salt)
.then((ret) => cb(null, ret))
.catch((err) => cb(err, null))
async create2 (gasLimit, value, data, salt) {
return this.create(gasLimit, value, data, salt)
}
}

Expand Down
36 changes: 9 additions & 27 deletions lib/evm/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,16 @@ module.exports = class Loop {
runState.static = prevStatic
}

handleOp (runState, opInfo) {
return new Promise((resolve, reject) => {
const opFn = this.getOpHandler(opInfo)
let args = [runState]
// create a callback for async opFunc
if (opInfo.async) {
args.push((err) => {
if (err) return reject(err)
return resolve()
})
}

try {
// run the opcode
opFn.apply(null, args)
} catch (e) {
if (e.errorType && e.errorType === 'VmError') {
return reject(e)
} else {
throw e
}
}
async handleOp (runState, opInfo) {
const opFn = this.getOpHandler(opInfo)
let args = [runState]

// call the callback if opFn was sync
if (!opInfo.async) {
return resolve()
}
})
// run the opcode
if (opInfo.async) {
await opFn.apply(null, args)
} else {
opFn.apply(null, args)
}
}

getOpHandler (opInfo) {
Expand Down
Loading

0 comments on commit ed5b1a9

Please sign in to comment.