aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-04-10 21:00:24 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-04-13 09:17:37 +0800
commite6221108b601938d6165cc1a0583d70c30e6e364 (patch)
treec838fb8e6fcc46285d9b0df59bd8ca898bc00ab9
parentbd48f181b588978461fb4651839c62bcac7888d4 (diff)
downloaddexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar.gz
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar.bz2
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar.lz
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar.xz
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.tar.zst
dexon-solidity-e6221108b601938d6165cc1a0583d70c30e6e364.zip
Move gasEstimate into CompilerStack
-rw-r--r--libsolidity/interface/CompilerStack.cpp85
-rw-r--r--libsolidity/interface/CompilerStack.h3
2 files changed, 88 insertions, 0 deletions
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 9ad28573..0fddd505 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -38,6 +38,7 @@
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/codegen/Compiler.h>
#include <libsolidity/interface/InterfaceHandler.h>
+#include <libsolidity/interface/GasEstimator.h>
#include <libsolidity/formal/Why3Translator.h>
#include <libevmasm/Exceptions.h>
@@ -841,3 +842,87 @@ string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) con
}
return ret;
}
+
+namespace
+{
+
+Json::Value gasToJson(GasEstimator::GasConsumption const& _gas)
+{
+ if (_gas.isInfinite || _gas.value > std::numeric_limits<Json::LargestUInt>::max())
+ return Json::Value(Json::nullValue);
+ else
+ return Json::Value(Json::LargestUInt(_gas.value));
+}
+
+}
+
+Json::Value CompilerStack::gasEstimates(string const& _contractName) const
+{
+ if (!assemblyItems(_contractName) && !runtimeAssemblyItems(_contractName))
+ return Json::Value();
+
+ using Gas = GasEstimator::GasConsumption;
+ Json::Value output(Json::objectValue);
+
+ if (eth::AssemblyItems const* items = assemblyItems(_contractName))
+ {
+ Gas executionGas = GasEstimator::functionalEstimation(*items);
+ u256 bytecodeSize(runtimeObject(_contractName).bytecode.size());
+ Gas codeDepositGas = bytecodeSize * eth::GasCosts::createDataGas;
+
+ Json::Value creation(Json::objectValue);
+ creation["codeDepositCost"] = gasToJson(codeDepositGas);
+ creation["executionCost"] = gasToJson(executionGas);
+ /// TODO: implement + overload to avoid the need of +=
+ executionGas += codeDepositGas;
+ creation["totalCost"] = gasToJson(executionGas);
+ output["creation"] = creation;
+ }
+
+ if (eth::AssemblyItems const* items = runtimeAssemblyItems(_contractName))
+ {
+ /// External functions
+ ContractDefinition const& contract = contractDefinition(_contractName);
+ Json::Value externalFunctions(Json::objectValue);
+ for (auto it: contract.interfaceFunctions())
+ {
+ string sig = it.second->externalSignature();
+ externalFunctions[sig] = gasToJson(GasEstimator::functionalEstimation(*items, sig));
+ }
+
+ if (contract.fallbackFunction())
+ /// This needs to be set to an invalid signature in order to trigger the fallback,
+ /// without the shortcut (of CALLDATSIZE == 0), and therefore to receive the upper bound.
+ /// An empty string ("") would work to trigger the shortcut only.
+ externalFunctions[""] = gasToJson(GasEstimator::functionalEstimation(*items, "INVALID"));
+
+ if (!externalFunctions.empty())
+ output["external"] = externalFunctions;
+
+ /// Internal functions
+ Json::Value internalFunctions(Json::objectValue);
+ for (auto const& it: contract.definedFunctions())
+ {
+ if (it->isPartOfExternalInterface() || it->isConstructor())
+ continue;
+
+ size_t entry = functionEntryPoint(_contractName, *it);
+ GasEstimator::GasConsumption gas = GasEstimator::GasConsumption::infinite();
+ if (entry > 0)
+ gas = GasEstimator::functionalEstimation(*items, entry, *it);
+
+ FunctionType type(*it);
+ string sig = it->name() + "(";
+ auto paramTypes = type.parameterTypes();
+ for (auto it = paramTypes.begin(); it != paramTypes.end(); ++it)
+ sig += (*it)->toString() + (it + 1 == paramTypes.end() ? "" : ",");
+ sig += ")";
+ internalFunctions[sig] = gasToJson(gas);
+ }
+
+ if (!internalFunctions.empty())
+ output["internal"] = internalFunctions;
+ }
+
+ return output;
+}
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 9c37eead..a34a34bb 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -173,6 +173,9 @@ public:
std::string const& onChainMetadata(std::string const& _contractName) const;
void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; }
+ /// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions
+ Json::Value gasEstimates(std::string const& _contractName) const;
+
/// @returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& scanner(std::string const& _sourceName = "") const;
/// @returns the parsed source unit with the supplied name.