From 99351aebe0c9ebbb06e34c18ecc19bc0c87d9d54 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Oct 2015 14:13:07 +0200 Subject: [PATCH] Compiler version stamp. --- libsolidity/Compiler.cpp | 6 ++++ libsolidity/CompilerContext.cpp | 9 ++++++ libsolidity/CompilerContext.h | 3 ++ libsolidity/Utils.h | 1 + libsolidity/Version.cpp | 38 +++++++++++++++++++++-- libsolidity/Version.h | 6 ++++ test/libsolidity/SolidityEndToEndTest.cpp | 11 +++++++ 7 files changed, 71 insertions(+), 3 deletions(-) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 1ef63bbfc..6fb09defb 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -68,6 +68,12 @@ void Compiler::compileContract( packIntoContractCreator(_contract, m_runtimeContext); if (m_optimize) m_context.optimise(m_optimizeRuns); + + if (_contract.isLibrary()) + { + solAssert(m_runtimeSub != size_t(-1), ""); + m_context.injectVersionStampIntoSub(m_runtimeSub); + } } void Compiler::compileClone( diff --git a/libsolidity/CompilerContext.cpp b/libsolidity/CompilerContext.cpp index 717627a55..fa7f9c770 100644 --- a/libsolidity/CompilerContext.cpp +++ b/libsolidity/CompilerContext.cpp @@ -20,10 +20,12 @@ * Utilities for the solidity compiler. */ +#include #include #include #include #include +#include using namespace std; @@ -177,6 +179,13 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node) updateSourceLocation(); } +void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) +{ + eth::Assembly& sub = m_asm.sub(_subIndex); + sub.injectStart(eth::Instruction::POP); + sub.injectStart(fromBigEndian(binaryVersion())); +} + eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel( FunctionDefinition const& _function, vector::const_iterator _searchStart diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 46ebfcf82..188650918 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -128,6 +128,9 @@ public: CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; } CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; } + /// Prepends "PUSH POP" + void injectVersionStampIntoSub(size_t _subIndex); + void optimise(unsigned _runs = 200) { m_asm.optimise(true, true, _runs); } eth::Assembly const& assembly() const { return m_asm; } diff --git a/libsolidity/Utils.h b/libsolidity/Utils.h index 05c5fa6f0..6c8e3b336 100644 --- a/libsolidity/Utils.h +++ b/libsolidity/Utils.h @@ -23,6 +23,7 @@ #pragma once #include +#include /// Assertion that throws an InternalCompilerError containing the given description if it is not met. #define solAssert(CONDITION, DESCRIPTION) \ diff --git a/libsolidity/Version.cpp b/libsolidity/Version.cpp index c6b5c509f..09a6d84b2 100644 --- a/libsolidity/Version.cpp +++ b/libsolidity/Version.cpp @@ -22,16 +22,19 @@ #include #include -#include -#include +#include #include +#include +#include +#include using namespace dev; using namespace dev::solidity; using namespace std; char const* dev::solidity::VersionNumber = ETH_PROJECT_VERSION; -extern string const dev::solidity::VersionString = + +string const dev::solidity::VersionString = string(dev::solidity::VersionNumber) + "-" + string(DEV_QUOTED(ETH_COMMIT_HASH)).substr(0, 8) + @@ -39,3 +42,32 @@ extern string const dev::solidity::VersionString = "/" DEV_QUOTED(ETH_BUILD_TYPE) "-" DEV_QUOTED(ETH_BUILD_PLATFORM) " linked to libethereum-" + eth::VersionStringLibEvmAsm; + +bytes dev::solidity::binaryVersion() +{ + bytes ret{0}; + size_t i = 0; + auto parseDecimal = [&]() + { + size_t ret = 0; + solAssert('0' <= VersionString[i] && VersionString[i] <= '9', ""); + for (; i < VersionString.size() && '0' <= VersionString[i] && VersionString[i] <= '9'; ++i) + ret = ret * 10 + (VersionString[i] - '0'); + return ret; + }; + ret.push_back(byte(parseDecimal())); + solAssert(i < VersionString.size() && VersionString[i] == '.', ""); + ++i; + ret.push_back(byte(parseDecimal())); + solAssert(i < VersionString.size() && VersionString[i] == '.', ""); + ++i; + ret.push_back(byte(parseDecimal())); + solAssert(i < VersionString.size() && VersionString[i] == '-', ""); + ++i; + solAssert(i + 7 < VersionString.size(), ""); + ret += fromHex(VersionString.substr(i, 8)); + solAssert(ret.size() == 1 + 3 + 4, ""); + + return ret; +} + diff --git a/libsolidity/Version.h b/libsolidity/Version.h index 6e00f07b4..fea739976 100644 --- a/libsolidity/Version.h +++ b/libsolidity/Version.h @@ -23,6 +23,7 @@ #pragma once #include +#include namespace dev { @@ -32,5 +33,10 @@ namespace solidity extern char const* VersionNumber; extern std::string const VersionString; +/// @returns a binary form of the version string, where A.B.C-HASH is encoded such that +/// the first byte is zero, the following three bytes encode A B and C (interpreted as decimals) +/// and HASH is interpreted as 8 hex digits and encoded into the last four bytes. +bytes binaryVersion(); + } } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index b46b405d6..3cfe49755 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5539,6 +5539,17 @@ BOOST_AUTO_TEST_CASE(calldata_offset) BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd"))); } +BOOST_AUTO_TEST_CASE(version_stamp_for_libraries) +{ + char const* sourceCode = "library lib {}"; + m_optimize = true; + bytes runtimeCode = compileAndRun(sourceCode, 0, "lib"); + BOOST_CHECK(runtimeCode.size() >= 8); + BOOST_CHECK_EQUAL(runtimeCode[0], int(eth::Instruction::PUSH6)); // might change once we switch to 1.x.x + BOOST_CHECK_EQUAL(runtimeCode[1], 1); // might change once we switch away from x.1.x + BOOST_CHECK_EQUAL(runtimeCode[7], int(eth::Instruction::POP)); +} + BOOST_AUTO_TEST_SUITE_END() }