diff options
-rw-r--r-- | ASTPrinter.cpp | 2 | ||||
-rw-r--r-- | ASTPrinter.h | 6 | ||||
-rw-r--r-- | GasEstimator.cpp (renamed from StructuralGasEstimator.cpp) | 36 | ||||
-rw-r--r-- | GasEstimator.h (renamed from StructuralGasEstimator.h) | 20 |
4 files changed, 47 insertions, 17 deletions
diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp index 0a170f8e..d29ace17 100644 --- a/ASTPrinter.cpp +++ b/ASTPrinter.cpp @@ -33,7 +33,7 @@ namespace solidity ASTPrinter::ASTPrinter( ASTNode const& _ast, string const& _source, - StructuralGasEstimator::ASTGasConsumption const& _gasCosts + GasEstimator::ASTGasConsumption const& _gasCosts ): m_indentation(0), m_source(_source), m_ast(&_ast), m_gasCosts(_gasCosts) { } diff --git a/ASTPrinter.h b/ASTPrinter.h index 25678c17..cdf651f3 100644 --- a/ASTPrinter.h +++ b/ASTPrinter.h @@ -24,7 +24,7 @@ #include <ostream> #include <libsolidity/ASTVisitor.h> -#include <libsolidity/StructuralGasEstimator.h> +#include <libsolidity/GasEstimator.h> namespace dev { @@ -42,7 +42,7 @@ public: ASTPrinter( ASTNode const& _ast, std::string const& _source = std::string(), - StructuralGasEstimator::ASTGasConsumption const& _gasCosts = StructuralGasEstimator::ASTGasConsumption() + GasEstimator::ASTGasConsumption const& _gasCosts = GasEstimator::ASTGasConsumption() ); /// Output the string representation of the AST to _stream. void print(std::ostream& _stream); @@ -133,7 +133,7 @@ private: int m_indentation; std::string m_source; ASTNode const* m_ast; - StructuralGasEstimator::ASTGasConsumption m_gasCosts; + GasEstimator::ASTGasConsumption m_gasCosts; std::ostream* m_ostream; }; diff --git a/StructuralGasEstimator.cpp b/GasEstimator.cpp index 9ce32ca5..18e3a5ca 100644 --- a/StructuralGasEstimator.cpp +++ b/GasEstimator.cpp @@ -20,12 +20,14 @@ * Gas consumption estimator working alongside the AST. */ -#include "StructuralGasEstimator.h" +#include "GasEstimator.h" #include <map> #include <functional> #include <memory> +#include <libdevcore/SHA3.h> #include <libevmasm/ControlFlowGraph.h> #include <libevmasm/KnownState.h> +#include <libevmasm/PathGasMeter.h> #include <libsolidity/AST.h> #include <libsolidity/ASTVisitor.h> @@ -34,13 +36,13 @@ using namespace dev; using namespace dev::eth; using namespace dev::solidity; -StructuralGasEstimator::ASTGasConsumptionSelfAccumulated StructuralGasEstimator::performEstimation( +GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimation( AssemblyItems const& _items, vector<ASTNode const*> const& _ast ) { solAssert(std::count(_ast.begin(), _ast.end(), nullptr) == 0, ""); - map<SourceLocation, GasMeter::GasConsumption> particularCosts; + map<SourceLocation, GasConsumption> particularCosts; ControlFlowGraph cfg(_items); for (BasicBlock const& block: cfg.optimisedBlocks()) @@ -72,7 +74,7 @@ StructuralGasEstimator::ASTGasConsumptionSelfAccumulated StructuralGasEstimator: return gasCosts; } -map<ASTNode const*, GasMeter::GasConsumption> StructuralGasEstimator::breakToStatementLevel( +map<ASTNode const*, GasMeter::GasConsumption> GasEstimator::breakToStatementLevel( ASTGasConsumptionSelfAccumulated const& _gasCosts, vector<ASTNode const*> const& _roots ) @@ -99,7 +101,7 @@ map<ASTNode const*, GasMeter::GasConsumption> StructuralGasEstimator::breakToSta // we use the location of a node if // - its statement depth is 0 or // - its statement depth is undefined but the parent's statement depth is at least 1 - map<ASTNode const*, GasMeter::GasConsumption> gasCosts; + map<ASTNode const*, GasConsumption> gasCosts; auto onNodeSecondPass = [&](ASTNode const& _node) { return statementDepth.count(&_node); @@ -121,7 +123,28 @@ map<ASTNode const*, GasMeter::GasConsumption> StructuralGasEstimator::breakToSta return gasCosts; } -set<ASTNode const*> StructuralGasEstimator::finestNodesAtLocation( +GasEstimator::GasConsumption GasEstimator::functionalEstimation( + AssemblyItems const& _items, + string const& _signature +) +{ + auto state = make_shared<KnownState>(); + + ExpressionClasses& classes = state->expressionClasses(); + using Id = ExpressionClasses::Id; + using Ids = vector<Id>; + Id hashValue = classes.find(u256(FixedHash<4>::Arith(FixedHash<4>(dev::sha3(_signature))))); + Id calldata = classes.find(eth::Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); + classes.forceEqual(hashValue, eth::Instruction::DIV, Ids{ + calldata, + classes.find(u256(1) << (8 * 28)) + }); + + PathGasMeter meter(_items); + return meter.estimateMax(0, state); +} + +set<ASTNode const*> GasEstimator::finestNodesAtLocation( vector<ASTNode const*> const& _roots ) { @@ -140,4 +163,3 @@ set<ASTNode const*> StructuralGasEstimator::finestNodesAtLocation( root->accept(visitor); return nodes; } - diff --git a/StructuralGasEstimator.h b/GasEstimator.h index ddc7c186..32e95fac 100644 --- a/StructuralGasEstimator.h +++ b/GasEstimator.h @@ -34,17 +34,18 @@ namespace dev namespace solidity { -class StructuralGasEstimator +struct GasEstimator { public: - using ASTGasConsumption = std::map<ASTNode const*, eth::GasMeter::GasConsumption>; + using GasConsumption = eth::GasMeter::GasConsumption; + using ASTGasConsumption = std::map<ASTNode const*, GasConsumption>; using ASTGasConsumptionSelfAccumulated = - std::map<ASTNode const*, std::array<eth::GasMeter::GasConsumption, 2>>; + std::map<ASTNode const*, std::array<GasConsumption, 2>>; /// Estimates the gas consumption for every assembly item in the given assembly and stores /// it by source location. /// @returns a mapping from each AST node to a pair of its particular and syntactically accumulated gas costs. - ASTGasConsumptionSelfAccumulated performEstimation( + static ASTGasConsumptionSelfAccumulated structuralEstimation( eth::AssemblyItems const& _items, std::vector<ASTNode const*> const& _ast ); @@ -52,14 +53,21 @@ public: /// the following source locations are part of the mapping: /// 1. source locations of statements that do not contain other statements /// 2. maximal source locations that do not overlap locations coming from the first rule - ASTGasConsumption breakToStatementLevel( + static ASTGasConsumption breakToStatementLevel( ASTGasConsumptionSelfAccumulated const& _gasCosts, std::vector<ASTNode const*> const& _roots ); + /// @returns the estimated gas consumption by the (public or external) function with the + /// given signature. If no signature is given, estimates the maximum gas usage. + static GasConsumption functionalEstimation( + eth::AssemblyItems const& _items, + std::string const& _signature = "" + ); + private: /// @returns the set of AST nodes which are the finest nodes at their location. - std::set<ASTNode const*> finestNodesAtLocation(std::vector<ASTNode const*> const& _roots); + static std::set<ASTNode const*> finestNodesAtLocation(std::vector<ASTNode const*> const& _roots); }; } |