Merge pull request #1983 from chriseth/sol_knowledgeableGasEstimation

Gas estimation taking known state into account.
This commit is contained in:
chriseth 2015-05-20 18:31:47 +02:00
commit 42a36548e2
2 changed files with 66 additions and 5 deletions

View File

@ -21,6 +21,8 @@
*/ */
#include <test/libsolidity/solidityExecutionFramework.h> #include <test/libsolidity/solidityExecutionFramework.h>
#include <libevmasm/GasMeter.h>
#include <libevmasm/KnownState.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/StructuralGasEstimator.h> #include <libsolidity/StructuralGasEstimator.h>
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
@ -55,8 +57,21 @@ public:
); );
} }
void testCreationTimeGas(string const& _sourceCode, string const& _contractName = "")
{
compileAndRun(_sourceCode);
auto state = make_shared<KnownState>();
GasMeter meter(state);
GasMeter::GasConsumption gas;
for (AssemblyItem const& item: *m_compiler.getAssemblyItems(_contractName))
gas += meter.estimateMax(item);
u256 bytecodeSize(m_compiler.getRuntimeBytecode(_contractName).size());
gas += bytecodeSize * c_createDataGas;
BOOST_REQUIRE(!gas.isInfinite);
BOOST_CHECK(gas.value == m_gasUsed);
}
protected: protected:
dev::solidity::CompilerStack m_compiler;
map<ASTNode const*, eth::GasMeter::GasConsumption> m_gasCosts; map<ASTNode const*, eth::GasMeter::GasConsumption> m_gasCosts;
}; };
@ -91,6 +106,49 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs)
} }
} }
BOOST_AUTO_TEST_CASE(simple_contract)
{
// Tests a simple "deploy contract" code without constructor. The actual contract is not relevant.
char const* sourceCode = R"(
contract test {
bytes32 public shaValue;
function f(uint a) {
shaValue = sha3(a);
}
}
)";
testCreationTimeGas(sourceCode);
}
BOOST_AUTO_TEST_CASE(store_sha3)
{
char const* sourceCode = R"(
contract test {
bytes32 public shaValue;
function test(uint a) {
shaValue = sha3(a);
}
}
)";
testCreationTimeGas(sourceCode);
}
BOOST_AUTO_TEST_CASE(updating_store)
{
char const* sourceCode = R"(
contract test {
uint data;
uint data2;
function test() {
data = 1;
data = 2;
data2 = 0;
}
}
)";
testCreationTimeGas(sourceCode);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

View File

@ -44,11 +44,11 @@ public:
bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "") bytes const& compileAndRun(std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "")
{ {
dev::solidity::CompilerStack compiler(m_addStandardSources); m_compiler.reset(false, m_addStandardSources);
compiler.addSource("", _sourceCode); m_compiler.addSource("", _sourceCode);
ETH_TEST_REQUIRE_NO_THROW(compiler.compile(m_optimize), "Compiling contract failed"); ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize), "Compiling contract failed");
bytes code = compiler.getBytecode(_contractName); bytes code = m_compiler.getBytecode(_contractName);
sendMessage(code, true, _value); sendMessage(code, true, _value);
BOOST_REQUIRE(!m_output.empty()); BOOST_REQUIRE(!m_output.empty());
return m_output; return m_output;
@ -160,12 +160,14 @@ protected:
BOOST_REQUIRE(executive.go()); BOOST_REQUIRE(executive.go());
m_state.noteSending(m_sender); m_state.noteSending(m_sender);
executive.finalize(); executive.finalize();
m_gasUsed = executive.gasUsed();
m_output = executive.out().toVector(); m_output = executive.out().toVector();
m_logs = executive.logs(); m_logs = executive.logs();
} }
bool m_optimize = false; bool m_optimize = false;
bool m_addStandardSources = false; bool m_addStandardSources = false;
dev::solidity::CompilerStack m_compiler;
Address m_sender; Address m_sender;
Address m_contractAddress; Address m_contractAddress;
eth::State m_state; eth::State m_state;
@ -173,6 +175,7 @@ protected:
u256 const m_gas = 100000000; u256 const m_gas = 100000000;
bytes m_output; bytes m_output;
eth::LogEntries m_logs; eth::LogEntries m_logs;
u256 m_gasUsed;
}; };
} }