Merge pull request #2187 from ethereum/testOptimizer

Add recomputation check for number representation.
This commit is contained in:
Alex Beregszaszi 2017-04-27 16:26:08 +01:00 committed by GitHub
commit 2c8b770062
2 changed files with 60 additions and 1 deletions

View File

@ -232,6 +232,54 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
}
}
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
{
// This is a tiny EVM that can only evaluate some instructions.
vector<u256> stack;
for (AssemblyItem const& item: _routine)
{
switch (item.type())
{
case Operation:
{
if (stack.size() < size_t(item.arguments()))
return false;
u256* sp = &stack.back();
switch (item.instruction())
{
case Instruction::MUL:
sp[-1] = sp[0] * sp[-1];
break;
case Instruction::EXP:
if (sp[-1] > 0xff)
return false;
sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
break;
case Instruction::ADD:
sp[-1] = sp[0] + sp[-1];
break;
case Instruction::SUB:
sp[-1] = sp[0] - sp[-1];
break;
case Instruction::NOT:
sp[0] = ~sp[0];
break;
default:
return false;
}
stack.resize(stack.size() + item.deposit());
break;
}
case Push:
stack.push_back(item.data());
break;
default:
return false;
}
}
return stack.size() == 1 && stack.front() == _value;
}
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
{
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);

View File

@ -21,10 +21,14 @@
#pragma once
#include <vector>
#include <libevmasm/Exceptions.h>
#include <libdevcore/Assertions.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <vector>
namespace dev
{
namespace eth
@ -130,6 +134,11 @@ public:
ConstantOptimisationMethod(_params, _value)
{
m_routine = findRepresentation(m_value);
assertThrow(
checkRepresentation(m_value, m_routine),
OptimizerException,
"Invalid constant expression created."
);
}
virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
@ -141,6 +150,8 @@ public:
protected:
/// Tries to recursively find a way to compute @a _value.
AssemblyItems findRepresentation(u256 const& _value);
/// Recomputes the value from the calculated representation and checks for correctness.
bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine);
bigint gasNeeded(AssemblyItems const& _routine);
/// Counter for the complexity of optimization, will stop when it reaches zero.