diff --git a/lib/modules/fuzzer/index.js b/lib/modules/fuzzer/index.js index e086f7d6b..cd6539258 100644 --- a/lib/modules/fuzzer/index.js +++ b/lib/modules/fuzzer/index.js @@ -17,7 +17,23 @@ class ContractFuzzer { generateFuzz(iterations, contract) { const self = this; let fuzzMap = {}; - for (let i = 0; i < iterations; i++) { + contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0).forEach((abiMethod) => { + let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name; + let inputTypes = abiMethod.inputs.map(input => input.type); + self.logger.debug("input method:", name); + fuzzMap[name] = {}; + for (let i = 0; i < iterations; i++) { + fuzzMap[name][i] = {}; + self.logger.debug("iteration:", i); + fuzzMap[name][i] = inputTypes.map(input => this.getTypeFuzz(input)); + } + for (let key in fuzzMap[name]) self.logger.info(name + ":" + fuzzMap[name][key]); + }); + self.logger.info('\n'); + return fuzzMap; + } + + /*for (let i = 0; i < iterations; i++) { fuzzMap[i] = {}; contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0).forEach((abiMethod) => { let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name; @@ -28,9 +44,9 @@ class ContractFuzzer { }); self.logger.info('\n'); for (let key in fuzzMap[i]) self.logger.info(key + ":" + fuzzMap[i][key]); - } + }); return fuzzMap; - } + }*/ getTypeFuzz(typeString) { const self = this; diff --git a/lib/modules/gasEstimator/index.js b/lib/modules/gasEstimator/index.js index 329f869ba..f67615815 100644 --- a/lib/modules/gasEstimator/index.js +++ b/lib/modules/gasEstimator/index.js @@ -1,3 +1,5 @@ +const async = require('async'); +const _ = require('underscore'); const ContractFuzzer = require('../fuzzer'); /*global web3*/ @@ -10,42 +12,45 @@ class GasEstimator { this.fuzzer = new ContractFuzzer(embark); } - estimateGas(contractName) { + estimateGas(contractName, cb) { const self = this; let gasMap = {}; self.events.request('contracts:contract', contractName, (contract) => { self.logger.info("Generating three rounds of fuzz for contract -- ", contractName); let fuzzMap = self.fuzzer.generateFuzz(3, contract); self.logger.info("-- Beginning gastimation for contract -- " + contractName); - let tempGasMap = {}; let contractObj = new web3.eth.Contract(contract.abiDefinition, contract.deployedAddress); - for (let i = 0; i < 3; i++) { - tempGasMap[i] = {}; - for (let name in fuzzMap[i]) { - tempGasMap[i][name] = contractObj.methods[name] - .apply(contractObj.methods[name], fuzzMap[i][name]) - .estimateGas() - .then(estimatedGas => estimatedGas) - .catch(err => err); - } - } - contract.abiDefinition.forEach((abiMethod) => { - let name = abiMethod.name; - console.log("estimaticating the gas for method name: ", name); - if (abiMethod.type === "constructor") { - gasMap[name] = contract.gasEstimates.creation.totalCost; - } else if (abiMethod.inputs.length === 0) { - gasMap[name] = contractObj.methods[name].apply(contractObj.methods[name], []).estimateGas() - .then(estimatedGas => estimatedGas) - .catch(err => err); - } else if (tempGasMap[0][name] !== tempGasMap[1][name] && tempGasMap[1][name] !== tempGasMap[2][name]) { - gasMap[name] = 'variable'; + async.each(contract.abiDefinition, function(abiMethod, gasCb) => { + let name = abiMethod.name; + if (abiMethod.type === "constructor") { + // already provided for us + gasCb(null, 'constructor', contract.gasEstimates.creation.totalCost); + } else if (abiMethod.inputs.length === 0) { + // just run it and register it + contractObj.methods[name] + .apply(contractObj.methods[name], []) + .estimateGas(function(err, gasAmount) { + gasCb(err, gasAmount, name); + }); } else { - gasMap[name] = tempGasMap[name][0]; + // async concatenate all the fuzz values and their gas cost outputs and check for equality + async.concat(fuzzMap[name], function(values, getVarianceCb) { + contractObj.methods[name] + .apply(contractObj.methods[name], values) + .estimateGas(function(err, gasAmount) { + getVarianceCb(err, [gasAmount]); + }); + }, function(err, variance) { + if (err) gasCb(err) + else if (variance.reduce(_.isEqual) gasCb(null, variance[0], name); + gasCb(null, 'variable', name); + }); + }); + }, + function(err, gasAmount, name) => { + if (err) return cb(err); + gasMap[name] = gasAmount; } - console.log("Estimate Gas ForEAch: ", gasMap[name]); - }); - return gasMap; }); } }