Skip to content

Commit

Permalink
Merge pull request ethereum#2187 from ethereum/testOptimizer
Browse files Browse the repository at this point in the history
Add recomputation check for number representation.
  • Loading branch information
axic authored Apr 27, 2017
2 parents 122dc65 + 0e91b8f commit 2c8b770
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
48 changes: 48 additions & 0 deletions libevmasm/ConstantOptimiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 12 additions & 1 deletion libevmasm/ConstantOptimiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -130,6 +134,11 @@ class ComputeMethod: public ConstantOptimisationMethod
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); }
Expand All @@ -141,6 +150,8 @@ class ComputeMethod: public ConstantOptimisationMethod
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.
Expand Down

0 comments on commit 2c8b770

Please sign in to comment.