From c5d14ce933e3f1d4814c73cbb6d7fe7062caaa06 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 9 Jan 2015 17:02:39 +0100 Subject: [PATCH 1/6] Work in prgress for creating natspec in alethzero at contract creation --- CompilerStack.cpp | 7 +++++++ CompilerStack.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/CompilerStack.cpp b/CompilerStack.cpp index 174f9cd22..547e5fe21 100644 --- a/CompilerStack.cpp +++ b/CompilerStack.cpp @@ -200,6 +200,13 @@ bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimiz return stack.compile(_sourceCode, _optimize); } +dev::h256 CompilerStack::getContractCodeHash(std::string const& _contractName) +{ + //LTODO + (void) _contractName; + return dev::h256(""); +} + void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; diff --git a/CompilerStack.h b/CompilerStack.h index afc9a5162..6b60f1dd3 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace dev { namespace solidity { @@ -104,6 +105,9 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); + /// Get the runtime context's code hash for a contract. LTODO + dev::h256 getContractCodeHash(std::string const& _contractName); + private: /** * Information pertaining to one source unit, filled gradually during parsing and compilation. From a253abf0623aec5ebbf8fa8b4ec3b00596c724ee Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 12 Jan 2015 17:13:27 +0100 Subject: [PATCH 2/6] Alethzero: Showing a contract's function's hashes at creation --- CompilerStack.cpp | 18 ++++++++++++++++++ CompilerStack.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/CompilerStack.cpp b/CompilerStack.cpp index 547e5fe21..f0d2e7f75 100644 --- a/CompilerStack.cpp +++ b/CompilerStack.cpp @@ -179,6 +179,24 @@ string const& CompilerStack::getMetadata(string const& _contractName, Documentat return *(*doc); } +std::string const CompilerStack::getFunctionHashes(std::string const& _contractName) +{ + if (!m_parseSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + + std::string ret = ""; + Contract const& contract = getContract(_contractName); + auto interfaceFunctions = contract.contract->getInterfaceFunctions(); + + for (auto const& it: interfaceFunctions) + { + ret += it.first.abridged(); + ret += " :"; + ret += it.second->getName() + "\n"; + } + return ret; +} + Scanner const& CompilerStack::getScanner(string const& _sourceName) const { return *getSource(_sourceName).scanner; diff --git a/CompilerStack.h b/CompilerStack.h index 6b60f1dd3..da0adf57e 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -93,6 +93,9 @@ public: /// Can be one of 4 types defined at @c DocumentationType std::string const& getMetadata(std::string const& _contractName, DocumentationType _type) const; + /// Convenience function to return all contract method hashes in a string + std::string const getFunctionHashes(std::string const& _contractName = ""); + /// @returns the previously used scanner, useful for counting lines during error reporting. Scanner const& getScanner(std::string const& _sourceName = "") const; /// @returns the parsed source unit with the supplied name. From 12e000e0d327ead61092c890d0e5a359a9b9a54d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 13 Jan 2015 15:59:42 +0100 Subject: [PATCH 3/6] A first version of Natspec warning popup - Runtime Contract code hash can now be retrieved from the Compiler - Using the hash the Natspec handler stores and later retrieves Natspec JSON for a given contract. --- Compiler.cpp | 5 ++--- Compiler.h | 2 ++ CompilerStack.cpp | 20 +++++++++++++------- CompilerStack.h | 10 +++++++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Compiler.cpp b/Compiler.cpp index 782a7efe2..bd6571b9a 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -50,10 +50,9 @@ void Compiler::compileContract(ContractDefinition const& _contract, vectoraccept(*this); // Swap the runtime context with the creation-time context - CompilerContext runtimeContext; - swap(m_context, runtimeContext); + swap(m_context, m_runtimeContext); initializeContext(_contract, _magicGlobals, _contracts); - packIntoContractCreator(_contract, runtimeContext); + packIntoContractCreator(_contract, m_runtimeContext); } void Compiler::initializeContext(ContractDefinition const& _contract, vector const& _magicGlobals, diff --git a/Compiler.h b/Compiler.h index e83d1ed3a..c229a7a8a 100644 --- a/Compiler.h +++ b/Compiler.h @@ -35,6 +35,7 @@ public: void compileContract(ContractDefinition const& _contract, std::vector const& _magicGlobals, std::map const& _contracts); bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); } + bytes getRuntimeBytecode() { return m_runtimeContext.getAssembledBytecode(m_optimize);} void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } private: @@ -70,6 +71,7 @@ private: bool const m_optimize; CompilerContext m_context; + CompilerContext m_runtimeContext; std::vector m_breakTags; ///< tag to jump to for a "break" statement std::vector m_continueTags; ///< tag to jump to for a "continue" statement eth::AssemblyItem m_returnTag; ///< tag to jump to for a "return" statement diff --git a/CompilerStack.cpp b/CompilerStack.cpp index f0d2e7f75..b06423497 100644 --- a/CompilerStack.cpp +++ b/CompilerStack.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace std; namespace dev @@ -117,6 +119,7 @@ void CompilerStack::compile(bool _optimize) contractBytecode); Contract& compiledContract = m_contracts[contract->getName()]; compiledContract.bytecode = compiler->getAssembledBytecode(); + compiledContract.runtimeBytecode = compiler->getRuntimeBytecode(); compiledContract.compiler = move(compiler); contractBytecode[compiledContract.contract] = &compiledContract.bytecode; } @@ -134,6 +137,16 @@ bytes const& CompilerStack::getBytecode(string const& _contractName) const return getContract(_contractName).bytecode; } +bytes const& CompilerStack::getRuntimeBytecode(std::string const& _contractName) const +{ + return getContract(_contractName).runtimeBytecode; +} + +dev::h256 CompilerStack::getContractCodeHash(std::string const& _contractName) const +{ + return dev::sha3(getRuntimeBytecode(_contractName)); +} + void CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName) const { getContract(_contractName).compiler->streamAssembly(_outStream); @@ -218,13 +231,6 @@ bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimiz return stack.compile(_sourceCode, _optimize); } -dev::h256 CompilerStack::getContractCodeHash(std::string const& _contractName) -{ - //LTODO - (void) _contractName; - return dev::h256(""); -} - void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; diff --git a/CompilerStack.h b/CompilerStack.h index da0adf57e..202f1b321 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -76,7 +76,13 @@ public: /// @returns the compiled bytecode bytes const& compile(std::string const& _sourceCode, bool _optimize = false); + /// Gets the assembled bytecode for a contract bytes const& getBytecode(std::string const& _contractName = "") const; + /// Get the runtime context's bytecode for a contract + bytes const& getRuntimeBytecode(std::string const& _contractName = "") const; + /// Get the runtime context's code hash for a contract + dev::h256 getContractCodeHash(std::string const& _contractName = "") const; + /// Streams a verbose version of the assembly to @a _outStream. /// Prerequisite: Successful compilation. void streamAssembly(std::ostream& _outStream, std::string const& _contractName = "") const; @@ -108,9 +114,6 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); - /// Get the runtime context's code hash for a contract. LTODO - dev::h256 getContractCodeHash(std::string const& _contractName); - private: /** * Information pertaining to one source unit, filled gradually during parsing and compilation. @@ -128,6 +131,7 @@ private: ContractDefinition const* contract = nullptr; std::shared_ptr compiler; bytes bytecode; + bytes runtimeBytecode; std::shared_ptr interfaceHandler; mutable std::unique_ptr interface; mutable std::unique_ptr solidityInterface; From ac8ad058cf0cf4fdc73591393eee7f1611560862 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 13 Jan 2015 16:15:32 +0100 Subject: [PATCH 4/6] Natspec method key is now the Canonical Signature --- InterfaceHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InterfaceHandler.cpp b/InterfaceHandler.cpp index a5c6f4a1d..4c7ae5f45 100644 --- a/InterfaceHandler.cpp +++ b/InterfaceHandler.cpp @@ -106,7 +106,7 @@ std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefi if (!m_notice.empty()) {// since @notice is the only user tag if missing function should not appear user["notice"] = Json::Value(m_notice); - methods[it.second->getName()] = user; + methods[it.second->getCanonicalSignature()] = user; } } } @@ -162,7 +162,7 @@ std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefin method["return"] = m_return; if (!method.empty()) // add the function, only if we have any documentation to add - methods[it.second->getName()] = method; + methods[it.second->getCanonicalSignature()] = method; } } doc["methods"] = methods; From a78794e8721c8f8f80ec89de2bf8ba158796e39f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 14 Jan 2015 16:49:09 +0100 Subject: [PATCH 5/6] Fixes and additional checks for Natspec Popup authentication --- CompilerStack.cpp | 22 ++-------------------- CompilerStack.h | 9 +++------ 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/CompilerStack.cpp b/CompilerStack.cpp index b06423497..11d90d08b 100644 --- a/CompilerStack.cpp +++ b/CompilerStack.cpp @@ -137,12 +137,12 @@ bytes const& CompilerStack::getBytecode(string const& _contractName) const return getContract(_contractName).bytecode; } -bytes const& CompilerStack::getRuntimeBytecode(std::string const& _contractName) const +bytes const& CompilerStack::getRuntimeBytecode(string const& _contractName) const { return getContract(_contractName).runtimeBytecode; } -dev::h256 CompilerStack::getContractCodeHash(std::string const& _contractName) const +dev::h256 CompilerStack::getContractCodeHash(string const& _contractName) const { return dev::sha3(getRuntimeBytecode(_contractName)); } @@ -192,24 +192,6 @@ string const& CompilerStack::getMetadata(string const& _contractName, Documentat return *(*doc); } -std::string const CompilerStack::getFunctionHashes(std::string const& _contractName) -{ - if (!m_parseSuccessful) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); - - std::string ret = ""; - Contract const& contract = getContract(_contractName); - auto interfaceFunctions = contract.contract->getInterfaceFunctions(); - - for (auto const& it: interfaceFunctions) - { - ret += it.first.abridged(); - ret += " :"; - ret += it.second->getName() + "\n"; - } - return ret; -} - Scanner const& CompilerStack::getScanner(string const& _sourceName) const { return *getSource(_sourceName).scanner; diff --git a/CompilerStack.h b/CompilerStack.h index 202f1b321..29de69d59 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -76,11 +76,11 @@ public: /// @returns the compiled bytecode bytes const& compile(std::string const& _sourceCode, bool _optimize = false); - /// Gets the assembled bytecode for a contract + /// @returns the assembled bytecode for a contract. bytes const& getBytecode(std::string const& _contractName = "") const; - /// Get the runtime context's bytecode for a contract + /// @returns the runtime context's bytecode for a contract. bytes const& getRuntimeBytecode(std::string const& _contractName = "") const; - /// Get the runtime context's code hash for a contract + /// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor. dev::h256 getContractCodeHash(std::string const& _contractName = "") const; /// Streams a verbose version of the assembly to @a _outStream. @@ -99,9 +99,6 @@ public: /// Can be one of 4 types defined at @c DocumentationType std::string const& getMetadata(std::string const& _contractName, DocumentationType _type) const; - /// Convenience function to return all contract method hashes in a string - std::string const getFunctionHashes(std::string const& _contractName = ""); - /// @returns the previously used scanner, useful for counting lines during error reporting. Scanner const& getScanner(std::string const& _sourceName = "") const; /// @returns the parsed source unit with the supplied name. From 895a2852f47c456579ba6d9b4fa03659ed0a3af1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 14 Jan 2015 17:14:46 +0100 Subject: [PATCH 6/6] Minor style fixes --- CompilerStack.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CompilerStack.h b/CompilerStack.h index 29de69d59..aa55abe50 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -78,9 +78,9 @@ public: /// @returns the assembled bytecode for a contract. bytes const& getBytecode(std::string const& _contractName = "") const; - /// @returns the runtime context's bytecode for a contract. - bytes const& getRuntimeBytecode(std::string const& _contractName = "") const; /// @returns the runtime bytecode for the contract, i.e. the code that is returned by the constructor. + bytes const& getRuntimeBytecode(std::string const& _contractName = "") const; + /// @returns hash of the runtime bytecode for the contract, i.e. the code that is returned by the constructor. dev::h256 getContractCodeHash(std::string const& _contractName = "") const; /// Streams a verbose version of the assembly to @a _outStream.