Gas meter for Yul expressions.

This commit is contained in:
chriseth 2019-05-14 16:09:52 +02:00
parent 0a98fd4c7c
commit 1fc11f46fc
2 changed files with 88 additions and 0 deletions

View File

@ -22,10 +22,13 @@
#include <libyul/AsmData.h>
#include <libyul/Exceptions.h>
#include <libyul/Utilities.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/GasMeter.h>
#include <libdevcore/Visitor.h>
#include <libdevcore/CommonData.h>
using namespace std;
using namespace dev;
@ -151,6 +154,54 @@ void CodeCost::visit(Expression const& _expression)
ASTWalker::visit(_expression);
}
pair<size_t, size_t> GasMeter::gasCosts(
Expression const& _expression,
langutil::EVMVersion _evmVersion,
bool _isCreation
)
{
GasMeter gm(_evmVersion, _isCreation);
gm.visit(_expression);
return {gm.m_runGas, gm.m_dataGas};
}
void GasMeter::operator()(FunctionCall const&)
{
yulAssert(false, "Functions not implemented.");
}
void GasMeter::operator()(FunctionalInstruction const& _fun)
{
ASTWalker::operator()(_fun);
if (_fun.instruction == eth::Instruction::EXP)
m_runGas += dev::eth::GasCosts::expGas + dev::eth::GasCosts::expByteGas(m_evmVersion);
else
m_runGas += dev::eth::GasMeter::runGas(_fun.instruction);
m_dataGas += singleByteDataGas();
}
void GasMeter::operator()(Literal const& _lit)
{
m_runGas += dev::eth::GasMeter::runGas(dev::eth::Instruction::PUSH1);
m_dataGas +=
singleByteDataGas() +
size_t(dev::eth::GasMeter::dataGas(dev::toCompactBigEndian(valueOfLiteral(_lit), 1), m_isCreation));
}
void GasMeter::operator()(Identifier const&)
{
m_runGas += dev::eth::GasMeter::runGas(dev::eth::Instruction::DUP1);
m_dataGas += singleByteDataGas();
}
size_t GasMeter::singleByteDataGas() const
{
if (m_isCreation)
return dev::eth::GasCosts::txDataNonZeroGas;
else
return dev::eth::GasCosts::createDataGas;
}
void AssignmentCounter::operator()(Assignment const& _assignment)
{
for (auto const& variable: _assignment.variableNames)

View File

@ -21,6 +21,7 @@
#pragma once
#include <libyul/optimiser/ASTWalker.h>
#include <liblangutil/EVMVersion.h>
namespace yul
{
@ -84,6 +85,42 @@ private:
size_t m_cost = 0;
};
/**
* Gas meter for expressions only involving literals, identifiers and
* EVM instructions.
*
* Assumes that EXP is not used with exponents larger than a single byte.
*/
class GasMeter: public ASTWalker
{
public:
/// @returns the runtime costs and the data cost of
/// evaluating the given expression.
static std::pair<size_t, size_t> gasCosts(
Expression const& _expression,
langutil::EVMVersion _evmVersion,
bool _isCreation = false
);
private:
GasMeter(langutil::EVMVersion _evmVersion, bool _isCreation):
m_evmVersion(_evmVersion),
m_isCreation{_isCreation}
{}
void operator()(FunctionCall const& _funCall) override;
void operator()(FunctionalInstruction const& _instr) override;
void operator()(Literal const& _literal) override;
void operator()(Identifier const& _identifier) override;
private:
size_t singleByteDataGas() const;
langutil::EVMVersion m_evmVersion;
bool m_isCreation = false;
size_t m_runGas = 0;
size_t m_dataGas = 0;
};
/**
* Counts the number of assignments to every variable.
* Only works after running the Disambiguator.