From e121c8f3c7f710470ab9c32fe44636639d70502e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 19 Apr 2018 09:32:46 +0100 Subject: [PATCH] Store compiler version in CBOR metadata --- Changelog.md | 1 + cmake/EthBuildInfo.cmake | 3 ++ cmake/templates/BuildInfo.h.in | 3 ++ libsolidity/interface/CompilerStack.cpp | 4 +++ libsolidity/interface/Version.cpp | 38 ++++--------------------- libsolidity/interface/Version.h | 7 ++--- test/Metadata.cpp | 4 +-- test/libsolidity/Metadata.cpp | 15 ++++++++-- 8 files changed, 34 insertions(+), 41 deletions(-) diff --git a/Changelog.md b/Changelog.md index 043bb9e9a..e9173fa6a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: * SMTChecker: Support inherited state variables. * SMTChecker: Support tuples and function calls with multiple return values. * SMTChecker: Support ``delete``. + * Assembler: Encode the compiler version in the deployed bytecode. Bugfixes: diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake index b87d29f54..1316a888c 100644 --- a/cmake/EthBuildInfo.cmake +++ b/cmake/EthBuildInfo.cmake @@ -37,6 +37,9 @@ function(create_build_info NAME) -DETH_BUILD_COMPILER="${ETH_BUILD_COMPILER}" -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}" -DPROJECT_VERSION="${PROJECT_VERSION}" + -DPROJECT_VERSION_MAJOR="${PROJECT_VERSION_MAJOR}" + -DPROJECT_VERSION_MINOR="${PROJECT_VERSION_MINOR}" + -DPROJECT_VERSION_PATCH="${PROJECT_VERSION_PATCH}" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" ) include_directories("${PROJECT_BINARY_DIR}/include") diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 4b35df981..9c295a85f 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -1,6 +1,9 @@ #pragma once #define ETH_PROJECT_VERSION "@PROJECT_VERSION@" +#define ETH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define ETH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define ETH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define SOL_COMMIT_HASH "@SOL_COMMIT_HASH@" #define ETH_BUILD_TYPE "@ETH_BUILD_TYPE@" #define ETH_BUILD_OS "@ETH_BUILD_OS@" diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 45764f768..0f9c6f278 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1177,6 +1177,10 @@ bytes CompilerStack::createCBORMetadata(string const& _metadata, bool _experimen encoder.pushBytes("bzzr0", dev::swarmHash(_metadata).asBytes()); if (_experimentalMode) encoder.pushBool("experimental", true); + if (VersionIsRelease) + encoder.pushBytes("solc", VersionCompactBytes); + else + encoder.pushString("solc", VersionStringStrict); return encoder.serialise(); } diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index efd46d403..efb653d71 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -44,36 +44,10 @@ string const dev::solidity::VersionStringStrict = (string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) + (string(SOL_VERSION_COMMIT).empty() ? "" : "+" + string(SOL_VERSION_COMMIT)); -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(uint8_t(parseDecimal())); - solAssert(i < VersionString.size() && VersionString[i] == '.', ""); - ++i; - ret.push_back(uint8_t(parseDecimal())); - solAssert(i < VersionString.size() && VersionString[i] == '.', ""); - ++i; - ret.push_back(uint8_t(parseDecimal())); - solAssert(i < VersionString.size() && (VersionString[i] == '-' || VersionString[i] == '+'), ""); - ++i; - size_t commitpos = VersionString.find("commit."); - solAssert(commitpos != string::npos, ""); - i = commitpos + 7; - solAssert(i + 7 < VersionString.size(), ""); - bytes commitHash = fromHex(VersionString.substr(i, 8)); - solAssert(!commitHash.empty(), ""); - ret += commitHash; - solAssert(ret.size() == 1 + 3 + 4, ""); - - return ret; -} +bytes const dev::solidity::VersionCompactBytes = { + ETH_PROJECT_VERSION_MAJOR, + ETH_PROJECT_VERSION_MINOR, + ETH_PROJECT_VERSION_PATCH +}; +bool const dev::solidity::VersionIsRelease = string(SOL_VERSION_PRERELEASE).empty(); diff --git a/libsolidity/interface/Version.h b/libsolidity/interface/Version.h index 38d63ec68..14564c686 100644 --- a/libsolidity/interface/Version.h +++ b/libsolidity/interface/Version.h @@ -33,11 +33,8 @@ namespace solidity extern char const* VersionNumber; extern std::string const VersionString; extern std::string const VersionStringStrict; - -/// @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(); +extern bytes const VersionCompactBytes; +extern bool const VersionIsRelease; } } diff --git a/test/Metadata.cpp b/test/Metadata.cpp index b0f3c5994..bdbf427e9 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -41,9 +41,9 @@ bytes onlyMetadata(bytes const& _bytecode) size_t metadataSize = (_bytecode[size - 2] << 8) + _bytecode[size - 1]; if (size < (metadataSize + 2)) return bytes{}; - // Sanity check: assume the first byte is a fixed-size CBOR array with either 1 or 2 entries + // Sanity check: assume the first byte is a fixed-size CBOR array with either 2 or 3 entries unsigned char firstByte = _bytecode[size - metadataSize - 2]; - if (firstByte != 0xa1 && firstByte != 0xa2) + if (firstByte != 0xa2 && firstByte != 0xa3) return bytes{}; return bytes(_bytecode.end() - metadataSize - 2, _bytecode.end() - 2); } diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index ee30a31fa..a481f809e 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -69,7 +70,12 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) bytes hash = dev::swarmHash(metadata).asBytes(); BOOST_REQUIRE(hash.size() == 32); auto const cborMetadata = requireParsedCBORMetadata(bytecode); - BOOST_CHECK(cborMetadata.size() == 1); + BOOST_CHECK(cborMetadata.size() == 2); + BOOST_CHECK(cborMetadata.count("solc") == 1); + if (VersionIsRelease) + BOOST_CHECK(cborMetadata.at("solc") == toHex(VersionCompactBytes)); + else + BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict); BOOST_CHECK(cborMetadata.count("bzzr0") == 1); BOOST_CHECK(cborMetadata.at("bzzr0") == toHex(hash)); } @@ -95,7 +101,12 @@ BOOST_AUTO_TEST_CASE(metadata_stamp_experimental) bytes hash = dev::swarmHash(metadata).asBytes(); BOOST_REQUIRE(hash.size() == 32); auto const cborMetadata = requireParsedCBORMetadata(bytecode); - BOOST_CHECK(cborMetadata.size() == 2); + BOOST_CHECK(cborMetadata.size() == 3); + BOOST_CHECK(cborMetadata.count("solc") == 1); + if (VersionIsRelease) + BOOST_CHECK(cborMetadata.at("solc") == toHex(VersionCompactBytes)); + else + BOOST_CHECK(cborMetadata.at("solc") == VersionStringStrict); BOOST_CHECK(cborMetadata.count("bzzr0") == 1); BOOST_CHECK(cborMetadata.at("bzzr0") == toHex(hash)); BOOST_CHECK(cborMetadata.count("experimental") == 1);