From c2c39239d6f1d51addad97c0c5128983ef58011f Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 14 Nov 2016 16:02:57 +0100 Subject: [PATCH 1/2] Report infinite gas for calls. --- libevmasm/GasMeter.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 51f3cf1de..51dc34f47 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -128,24 +128,28 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item) case Instruction::CALLCODE: case Instruction::DELEGATECALL: { - gas = GasCosts::callGas; - if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0))) - gas += (*value); - else - gas = GasConsumption::infinite(); - if (_item.instruction() == Instruction::CALL) - gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. - int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; - if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) - gas += GasCosts::callValueTransferGas; - gas += memoryGas(-2 - valueSize, -3 - valueSize); - gas += memoryGas(-4 - valueSize, -5 - valueSize); +// We assume that we do not know the target contract and thus, the consumption is infinite. + gas = GasConsumption::infinite(); +// gas = GasCosts::callGas; +// if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0))) +// gas += (*value); +// else +// gas = GasConsumption::infinite(); +// if (_item.instruction() == Instruction::CALL) +// gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. +// int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; +// if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) +// gas += GasCosts::callValueTransferGas; +// gas += memoryGas(-2 - valueSize, -3 - valueSize); +// gas += memoryGas(-4 - valueSize, -5 - valueSize); break; } case Instruction::CREATE: - gas = GasCosts::createGas; - gas += memoryGas(-1, -2); - break; +// We assume that we do not know the target contract and thus, the consumption is infinite. +// gas = GasConsumption::infinite(); +// gas = GasCosts::createGas; +// gas += memoryGas(-1, -2); +// break; case Instruction::EXP: gas = GasCosts::expGas; if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(-1))) From bf5b0dc2d27a3c4139894daf627cf63b8cfb1864 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 14 Nov 2016 23:28:26 +0100 Subject: [PATCH 2/2] Keep old code. --- libevmasm/GasMeter.cpp | 48 ++++++++++++++++++++++++------------------ libevmasm/GasMeter.h | 3 ++- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 51dc34f47..da8b41e32 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -39,7 +39,7 @@ GasMeter::GasConsumption& GasMeter::GasConsumption::operator+=(GasConsumption co return *this; } -GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item) +GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _includeExternalCosts) { GasConsumption gas; switch (_item.type()) @@ -128,28 +128,36 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item) case Instruction::CALLCODE: case Instruction::DELEGATECALL: { -// We assume that we do not know the target contract and thus, the consumption is infinite. - gas = GasConsumption::infinite(); -// gas = GasCosts::callGas; -// if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0))) -// gas += (*value); -// else -// gas = GasConsumption::infinite(); -// if (_item.instruction() == Instruction::CALL) -// gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. -// int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; -// if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) -// gas += GasCosts::callValueTransferGas; -// gas += memoryGas(-2 - valueSize, -3 - valueSize); -// gas += memoryGas(-4 - valueSize, -5 - valueSize); + if (_includeExternalCosts) + // We assume that we do not know the target contract and thus, the consumption is infinite. + gas = GasConsumption::infinite(); + else + { + gas = GasCosts::callGas; + if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0))) + gas += (*value); + else + gas = GasConsumption::infinite(); + if (_item.instruction() == Instruction::CALL) + gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. + int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; + if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) + gas += GasCosts::callValueTransferGas; + gas += memoryGas(-2 - valueSize, -3 - valueSize); + gas += memoryGas(-4 - valueSize, -5 - valueSize); + } break; } case Instruction::CREATE: -// We assume that we do not know the target contract and thus, the consumption is infinite. -// gas = GasConsumption::infinite(); -// gas = GasCosts::createGas; -// gas += memoryGas(-1, -2); -// break; + if (_includeExternalCosts) + // We assume that we do not know the target contract and thus, the consumption is infinite. + gas = GasConsumption::infinite(); + else + { + gas = GasCosts::createGas; + gas += memoryGas(-1, -2); + } + break; case Instruction::EXP: gas = GasCosts::expGas; if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(-1))) diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index 1a607a9fc..ff1279096 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -102,7 +102,8 @@ public: /// @returns an upper bound on the gas consumed by the given instruction and updates /// the state. - GasConsumption estimateMax(AssemblyItem const& _item); + /// @param _inculdeExternalCosts if true, include costs caused by other contracts in calls. + GasConsumption estimateMax(AssemblyItem const& _item, bool _includeExternalCosts = true); u256 const& largestMemoryAccess() const { return m_largestMemoryAccess; }