From a98edb22e57ba497ba1ec675e47439089ce9e140 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 7 Sep 2016 18:30:53 +0200 Subject: [PATCH 01/21] Add Address module in the WhyML prelude In the `--formal` output, this commit adds a module called `Address`, which defines the address type as unsigned integer type bounded at 2^160-1. --- libsolidity/formal/Why3Translator.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index 834024fab..b441b1507 100644 --- a/libsolidity/formal/Why3Translator.cpp +++ b/libsolidity/formal/Why3Translator.cpp @@ -798,5 +798,14 @@ module UInt256 type t = uint256, constant max = max_uint256 end + +module Address + use import mach.int.Unsigned + type address + constant max_address: int = 0xffffffffffffffffffffffffffffffffffffffff (* 160 bit = 40 f's *) + clone export mach.int.Unsigned with + type t = address, + constant max = max_address +end )", 0}); } From 29ecc6fe31d56feaf5d5a04e84b12138baa0d1e7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Sep 2016 13:59:22 +0200 Subject: [PATCH 02/21] Remove leading zeroes in prerelease components. --- .gitignore | 3 +++ cmake/scripts/buildinfo.cmake | 1 + scripts/build_emscripten.sh | 2 +- scripts/release_ppa.sh | 2 +- scripts/travis-emscripten/publish_binary.sh | 5 ++++- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1ad199c10..e3e12421b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.commit_hash.txt +.prerelease.txt + # Compiled Object files *.slo *.lo diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index e2f8cb3eb..5f19df070 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -26,6 +26,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt) string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE) else() string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC) + string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}") endif() if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt) diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index da2c7df32..fe7ea11d1 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -29,7 +29,7 @@ set -e if [[ "$OSTYPE" != "darwin"* ]]; then - date -u +"nightly.%Y.%m.%d" > prerelease.txt + date -u +"nightly.%Y.%-m.%-d" > prerelease.txt ./scripts/travis-emscripten/install_deps.sh docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh fi diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 8e9dc2822..23c374e1a 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -54,7 +54,7 @@ cd solc version=`grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? CMakeLists.txt` commithash=`git rev-parse --short HEAD` committimestamp=`git show --format=%ci HEAD | head -n 1` -commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10` +commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./'` echo "$commithash" > commit_hash.txt if [ $branch = develop ] diff --git a/scripts/travis-emscripten/publish_binary.sh b/scripts/travis-emscripten/publish_binary.sh index e89e3ce3e..bfdf99065 100755 --- a/scripts/travis-emscripten/publish_binary.sh +++ b/scripts/travis-emscripten/publish_binary.sh @@ -34,7 +34,10 @@ VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_ test -n "$VER" VER="v$VER" COMMIT=$(git rev-parse --short HEAD) -DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%m.%d) +DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%-m.%-d) + +# remove leading zeros in components - they are not semver-compatible +COMMIT=$(echo "$COMMIT" | sed -e 's/^0*//') ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" From fb856c3f8d402ad73f9a7c2ed52a418396e60cee Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 8 Sep 2016 18:44:14 +0100 Subject: [PATCH 03/21] Document versioning behaviour --- docs/installing-solidity.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index ad27e5286..42d7bf984 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -6,6 +6,28 @@ Installing Solidity ################### +Versioning +========== + +Solidity versions follow `semantic versioning ` and in addition to +releases, **nightly development builds** are also made available. The nightly builds +are not guaranteed to be working and despite best efforts they might contain undocumented +and/or broken changes. + +After a release is made, the patch version level is bumped, because we assume that only +patch level changes follow. When changes are merged, the version should be bumped according +to semver and the severity of the change. Finally, a release is always made with the version +of the current nightly build, but without the ``prerelease`` specifier. + +Example: +- 0) the 0.4.0 release is made +- 1) nightly build has a version of 0.4.1 from now on +- 2) non-breaking changes are introduced - no change in version +- 3) a breaking change is introduced - version is bumped to 0.5.0 +- 4) the 0.5.0 release is made + +This behaviour works well with the version pragma. + Browser-Solidity ================ From 8040656d08e053fc2784000016103483438d0d35 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Sep 2016 17:24:02 +0200 Subject: [PATCH 04/21] Version bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ad9c0610..f190a5075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.1") +set(PROJECT_VERSION "0.4.2") project(solidity VERSION ${PROJECT_VERSION}) # Let's find our dependencies From 6c757ce4b8b8bef51de77180d1b914453655e238 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Sep 2016 17:43:36 +0200 Subject: [PATCH 05/21] Style. --- cmake/scripts/buildinfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index 5f19df070..f0e39906f 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -26,7 +26,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt) string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE) else() string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC) - string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}") + string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}") endif() if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt) From 00e8b059ea0ecd4a945657eabed17293dc73024a Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 7 Sep 2016 17:39:49 +0200 Subject: [PATCH 06/21] Explicitly convert the assert condition using bool() This allows a shared pointer as a condition because bool(std::shared_ptr) is defined. --- libdevcore/Assertions.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/libdevcore/Assertions.h b/libdevcore/Assertions.h index 7b4a4a765..05e0b0e5c 100644 --- a/libdevcore/Assertions.h +++ b/libdevcore/Assertions.h @@ -73,7 +73,7 @@ inline bool assertEqualAux(A const& _a, B const& _b, char const* _aStr, char con /// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong."); /// Do NOT supply an exception object as the second parameter. #define assertThrow(_condition, _ExceptionType, _description) \ - ::dev::assertThrowAux<_ExceptionType>(_condition, _description, __LINE__, __FILE__, ETH_FUNC) + ::dev::assertThrowAux<_ExceptionType>(!!(_condition), _description, __LINE__, __FILE__, ETH_FUNC) using errinfo_comment = boost::error_info; @@ -96,16 +96,4 @@ inline void assertThrowAux( ); } -template -inline void assertThrowAux( - void const* _pointer, - ::std::string const& _errorDescription, - unsigned _line, - char const* _file, - char const* _function -) -{ - assertThrowAux<_ExceptionType>(_pointer != nullptr, _errorDescription, _line, _file, _function); -} - } From c861cf579dc4c1303d6d215b5b31f930e1d6477e Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 7 Sep 2016 17:41:12 +0200 Subject: [PATCH 07/21] Translate mapping types into Why3 arrays when keys are integers Even when the keys are signed the translation is supposed to work because Why3 arrays allow negative indices. --- libsolidity/formal/Why3Translator.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index b441b1507..9a4a5cf5a 100644 --- a/libsolidity/formal/Why3Translator.cpp +++ b/libsolidity/formal/Why3Translator.cpp @@ -77,12 +77,26 @@ string Why3Translator::toFormalType(Type const& _type) const return "uint256"; } else if (auto type = dynamic_cast(&_type)) + { if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory)) { string base = toFormalType(*type->baseType()); if (!base.empty()) return "array " + base; } + } + else if (auto mappingType = dynamic_cast(&_type)) + { + solAssert(mappingType->keyType(), "A mappingType misses a keyType."); + if (dynamic_cast(&*mappingType->keyType())) + { + //@TODO Use the information from the key type and specify the length of the array as an invariant. + // Also the constructor need to specify the length of the array. + string valueType = toFormalType(*mappingType->valueType()); + if (!valueType.empty()) + return "array " + valueType; + } + } return ""; } From ac7c6ae7d240516b0c530d51645742320634430d Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 7 Sep 2016 20:16:46 +0200 Subject: [PATCH 08/21] toFormalType reports errors by an exception This allows error reporting without passing `ASTNode` to `toFormalType()` --- libsolidity/formal/Why3Translator.cpp | 87 +++++++++++++++++++++------ libsolidity/formal/Why3Translator.h | 5 +- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index 9a4a5cf5a..64aa9b4c0 100644 --- a/libsolidity/formal/Why3Translator.cpp +++ b/libsolidity/formal/Why3Translator.cpp @@ -80,9 +80,9 @@ string Why3Translator::toFormalType(Type const& _type) const { if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory)) { + // Not catching NoFormalType exception. Let the caller deal with it. string base = toFormalType(*type->baseType()); - if (!base.empty()) - return "array " + base; + return "array " + base; } } else if (auto mappingType = dynamic_cast(&_type)) @@ -92,13 +92,15 @@ string Why3Translator::toFormalType(Type const& _type) const { //@TODO Use the information from the key type and specify the length of the array as an invariant. // Also the constructor need to specify the length of the array. - string valueType = toFormalType(*mappingType->valueType()); - if (!valueType.empty()) - return "array " + valueType; + solAssert(mappingType->valueType(), "A mappingType misses a valueType."); + // Not catching NoFormalType exception. Let the caller deal with it. + string valueTypeFormal = toFormalType(*mappingType->valueType()); + return "array " + valueTypeFormal; } } - return ""; + BOOST_THROW_EXCEPTION(NoFormalType() + << errinfo_noFormalTypeFrom(_type.toString(true))); } void Why3Translator::addLine(string const& _line) @@ -156,9 +158,17 @@ bool Why3Translator::visit(ContractDefinition const& _contract) m_currentContract.stateVariables = _contract.stateVariables(); for (VariableDeclaration const* variable: m_currentContract.stateVariables) { - string varType = toFormalType(*variable->annotation().type); - if (varType.empty()) - fatalError(*variable, "Type not supported for state variable."); + string varType; + try + { + varType = toFormalType(*variable->annotation().type); + } + catch (NoFormalType &err) + { + string const* typeNamePtr = boost::get_error_info(err); + string typeName = typeNamePtr ? " \"" + *typeNamePtr + "\"" : ""; + fatalError(*variable, "Type" + typeName + " not supported for state variable."); + } addLine("mutable _" + variable->name() + ": " + varType); } unindent(); @@ -232,9 +242,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function) add(" (this: account)"); for (auto const& param: _function.parameters()) { - string paramType = toFormalType(*param->annotation().type); - if (paramType.empty()) - error(*param, "Parameter type not supported."); + string paramType; + try + { + paramType = toFormalType(*param->annotation().type); + } + catch (NoFormalType &err) + { + string const* typeName = boost::get_error_info(err); + error(*param, "Parameter type \"" + (typeName ? *typeName : "") + "\" not supported."); + } if (param->name().empty()) error(*param, "Anonymous function parameters not supported."); add(" (arg_" + param->name() + ": " + paramType + ")"); @@ -246,9 +263,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function) string retString = "("; for (auto const& retParam: _function.returnParameters()) { - string paramType = toFormalType(*retParam->annotation().type); - if (paramType.empty()) - error(*retParam, "Parameter type not supported."); + string paramType; + try + { + paramType = toFormalType(*retParam->annotation().type); + } + catch (NoFormalType &err) + { + string const* typeName = boost::get_error_info(err); + error(*retParam, "Parameter type " + (typeName ? *typeName : "") + " not supported."); + } if (retString.size() != 1) retString += ", "; retString += paramType; @@ -278,14 +302,32 @@ bool Why3Translator::visit(FunctionDefinition const& _function) { if (variable->name().empty()) error(*variable, "Unnamed return variables not yet supported."); - string varType = toFormalType(*variable->annotation().type); + string varType; + try + { + varType = toFormalType(*variable->annotation().type); + } + catch (NoFormalType &err) + { + string const* typeNamePtr = boost::get_error_info(err); + error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in return parameter not yet supported."); + } addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in"); } for (VariableDeclaration const* variable: _function.localVariables()) { if (variable->name().empty()) error(*variable, "Unnamed variables not yet supported."); - string varType = toFormalType(*variable->annotation().type); + string varType; + try + { + varType = toFormalType(*variable->annotation().type); + } + catch (NoFormalType &err) + { + string const* typeNamePtr = boost::get_error_info(err); + error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in variable declaration not yet supported."); + } addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in"); } addLine("try"); @@ -448,8 +490,15 @@ bool Why3Translator::visit(TupleExpression const& _node) bool Why3Translator::visit(UnaryOperation const& _unaryOperation) { - if (toFormalType(*_unaryOperation.annotation().type).empty()) - error(_unaryOperation, "Type not supported in unary operation."); + try + { + toFormalType(*_unaryOperation.annotation().type); + } + catch (NoFormalType &err) + { + string const* typeNamePtr = boost::get_error_info(err); + error(_unaryOperation, "Type \"" + (typeNamePtr ? *typeNamePtr : "") + "\" supported in unary operation."); + } switch (_unaryOperation.getOperator()) { diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h index 1b80ed613..22bfff895 100644 --- a/libsolidity/formal/Why3Translator.h +++ b/libsolidity/formal/Why3Translator.h @@ -60,9 +60,10 @@ private: /// Appends imports and constants use throughout the formal code. void appendPreface(); - /// @returns a string representation of the corresponding formal type or the empty string - /// if the type is not supported. + /// @returns a string representation of the corresponding formal type or throws NoFormalType exception. std::string toFormalType(Type const& _type) const; + using errinfo_noFormalTypeFrom = boost::error_info; + struct NoFormalType: virtual Exception {}; void indent() { newLine(); m_lines.back().indentation++; } void unindent(); From 4337e70cca58c02de15af258a0efc29062aa0a36 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 8 Sep 2016 09:47:01 +0200 Subject: [PATCH 09/21] Prepare for leaky exceptions Now toFormalType() reports errors by exceptions, they will be sometimes leaked to the wider context. This commits adds a catch. --- libsolidity/formal/Why3Translator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index 64aa9b4c0..f3831b40f 100644 --- a/libsolidity/formal/Why3Translator.cpp +++ b/libsolidity/formal/Why3Translator.cpp @@ -36,6 +36,10 @@ bool Why3Translator::process(SourceUnit const& _source) appendPreface(); _source.accept(*this); } + catch (NoFormalType&) + { + solAssert(false, "There is a call to toFormalType() that does not catch NoFormalType exceptions."); + } catch (FatalError& /*_e*/) { solAssert(m_errorOccured, ""); From ba7199720d8994233a6fef16a8600c5761c6809c Mon Sep 17 00:00:00 2001 From: Nick Savers Date: Fri, 9 Sep 2016 21:36:59 +0200 Subject: [PATCH 10/21] Update Solidity docs version to 0.4.1 --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d0e263623..485184f2a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -56,9 +56,9 @@ copyright = '2016, Ethereum' # built documents. # # The short X.Y version. -version = '0.2.0' +version = '0.4.1' # The full version, including alpha/beta/rc tags. -release = '0.2.0' +release = '0.4.1-develop' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From b720e7b03d3975d507cda309709e010c896d5fe3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 12 Sep 2016 11:15:49 +0200 Subject: [PATCH 11/21] Add Centos to install_deps.sh Added steps to otain solidity dependencies in CentOS. Tested those steps on a CentOS 6.8 machine, but the instructions are from memory. May need some tweaking. --- scripts/install_deps.sh | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 7c8523a8b..49c478b75 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -56,6 +56,8 @@ detect_linux_distro() { elif [ -f /etc/os-release ]; then # extract 'foo' from NAME=foo, only on the line with NAME=foo DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release) + elif [ -f /etc/centos-release ]; then + DISTRO=CentOS else DISTRO='' fi @@ -329,6 +331,45 @@ case $(uname -s) in sudo apt-get -y install eth ;; + +#------------------------------------------------------------------------------ +# CentOS +# CentOS needs some more testing. This is the general idea of packages +# needed, but some tweaking/improvements can definitely happen +#------------------------------------------------------------------------------ + CentOS) + # Make Sure we have the EPEL repos + sudo yum -y install epel-release + # Get g++ 4.8 + sudo rpm --import http://ftp.scientificlinux.org/linux/scientific/5x/x86_64/RPM-GPG-KEYs/RPM-GPG-KEY-cern + wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo + sudo yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils + + # Enable the devtoolset2 usage so global gcc/g++ become the 4.8 one. + # As per https://gist.github.com/stephenturner/e3bc5cfacc2dc67eca8b, what you should do afterwards is + # to add this line: + # source /opt/rh/devtoolset-2/enable + # to your bashrc so that this happens automatically at login + scl enable devtoolset-2 bash + + # Get cmake + sudo yum -y remove cmake + sudo yum -y install cmake3 + sudo ln -s /usr/bin/cmake3 /usr/bin/cmake + + # Get latest boost thanks to this guy: http://vicendominguez.blogspot.de/2014/04/boost-c-library-rpm-packages-for-centos.html + sudo yum -y remove boost-devel + sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo + sudo yum install boost-devel + + # And finally jsoncpp + sudo yum -y install jsoncpp-devel + + ;; + + + + *) #------------------------------------------------------------------------------ From 3cd760446e00e94120f49d63fb1976db8b42310b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 13 Sep 2016 12:13:21 +0100 Subject: [PATCH 12/21] Split versioning into two sections --- docs/installing-solidity.rst | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 42d7bf984..ebb7537be 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -12,21 +12,8 @@ Versioning Solidity versions follow `semantic versioning ` and in addition to releases, **nightly development builds** are also made available. The nightly builds are not guaranteed to be working and despite best efforts they might contain undocumented -and/or broken changes. - -After a release is made, the patch version level is bumped, because we assume that only -patch level changes follow. When changes are merged, the version should be bumped according -to semver and the severity of the change. Finally, a release is always made with the version -of the current nightly build, but without the ``prerelease`` specifier. - -Example: -- 0) the 0.4.0 release is made -- 1) nightly build has a version of 0.4.1 from now on -- 2) non-breaking changes are introduced - no change in version -- 3) a breaking change is introduced - version is bumped to 0.5.0 -- 4) the 0.5.0 release is made - -This behaviour works well with the version pragma. +and/or broken changes. We recommend to use the latest release. Package installers below +will use the latest release. Browser-Solidity ================ @@ -208,3 +195,20 @@ Alternatively, you can build for Windows on the command-line, like so: .. code:: bash cmake --build . --config RelWithDebInfo + +Important information about versioning +====================================== + +After a release is made, the patch version level is bumped, because we assume that only +patch level changes follow. When changes are merged, the version should be bumped according +to semver and the severity of the change. Finally, a release is always made with the version +of the current nightly build, but without the ``prerelease`` specifier. + +Example: +- 0) the 0.4.0 release is made +- 1) nightly build has a version of 0.4.1 from now on +- 2) non-breaking changes are introduced - no change in version +- 3) a breaking change is introduced - version is bumped to 0.5.0 +- 4) the 0.5.0 release is made + +This behaviour works well with the version pragma. From 9280954e726d2a4e16af8a41797aba1f495f326f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 14 Sep 2016 22:29:11 +0200 Subject: [PATCH 13/21] Add warning for CentOS dependencies --- scripts/install_deps.sh | 50 +++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index 49c478b75..334c62d4b 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -338,32 +338,38 @@ case $(uname -s) in # needed, but some tweaking/improvements can definitely happen #------------------------------------------------------------------------------ CentOS) - # Make Sure we have the EPEL repos - sudo yum -y install epel-release - # Get g++ 4.8 - sudo rpm --import http://ftp.scientificlinux.org/linux/scientific/5x/x86_64/RPM-GPG-KEYs/RPM-GPG-KEY-cern - wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo - sudo yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils + read -p "This script will heavily modify your system in order to allow for compilation of Solidity. Are you sure? [Y/N]" -n 1 -r + if [[ $REPLY =~ ^[Yy]$ ]]; then + # Make Sure we have the EPEL repos + sudo yum -y install epel-release + # Get g++ 4.8 + sudo rpm --import http://ftp.scientificlinux.org/linux/scientific/5x/x86_64/RPM-GPG-KEYs/RPM-GPG-KEY-cern + wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo + sudo yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils - # Enable the devtoolset2 usage so global gcc/g++ become the 4.8 one. - # As per https://gist.github.com/stephenturner/e3bc5cfacc2dc67eca8b, what you should do afterwards is - # to add this line: - # source /opt/rh/devtoolset-2/enable - # to your bashrc so that this happens automatically at login - scl enable devtoolset-2 bash + # Enable the devtoolset2 usage so global gcc/g++ become the 4.8 one. + # As per https://gist.github.com/stephenturner/e3bc5cfacc2dc67eca8b, what you should do afterwards is + # to add this line: + # source /opt/rh/devtoolset-2/enable + # to your bashrc so that this happens automatically at login + scl enable devtoolset-2 bash - # Get cmake - sudo yum -y remove cmake - sudo yum -y install cmake3 - sudo ln -s /usr/bin/cmake3 /usr/bin/cmake + # Get cmake + sudo yum -y remove cmake + sudo yum -y install cmake3 + sudo ln -s /usr/bin/cmake3 /usr/bin/cmake - # Get latest boost thanks to this guy: http://vicendominguez.blogspot.de/2014/04/boost-c-library-rpm-packages-for-centos.html - sudo yum -y remove boost-devel - sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo - sudo yum install boost-devel + # Get latest boost thanks to this guy: http://vicendominguez.blogspot.de/2014/04/boost-c-library-rpm-packages-for-centos.html + sudo yum -y remove boost-devel + sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo + sudo yum install boost-devel - # And finally jsoncpp - sudo yum -y install jsoncpp-devel + # And finally jsoncpp + sudo yum -y install jsoncpp-devel + else + echo "Aborted CentOS Solidity Dependency Installation"; + exit 1 + fi ;; From af86bfb07df801d4b9b2d9782f3a6c764a2b9859 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Sep 2016 01:47:16 +0200 Subject: [PATCH 14/21] Force commit hash to 8 digits. --- cmake/scripts/buildinfo.cmake | 13 ++++++++----- scripts/release_ppa.sh | 2 +- scripts/travis-emscripten/publish_binary.sh | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index f0e39906f..e6077a349 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -34,7 +34,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt) string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH) else() execute_process( - COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD + COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse --short=8 HEAD OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) execute_process( @@ -48,14 +48,17 @@ if (SOL_COMMIT_HASH) string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH) endif() -if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) - set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod") -endif() - if (NOT SOL_COMMIT_HASH) message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or " "supply a file called commit_hash.txt") endif() +if (NOT SOL_COMMIT_HASH MATCHES [a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]) + message(FATAL_ERROR "Malformed commit hash \"${SOL_COMMIT_HASH}\". It has to consist of exactly 8 hex digits.") +endif() + +if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) + set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod") +endif() set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}") diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 23c374e1a..6a30faf52 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -52,7 +52,7 @@ mv solidity solc # Determine version cd solc version=`grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? CMakeLists.txt` -commithash=`git rev-parse --short HEAD` +commithash=`git rev-parse --short=8 HEAD` committimestamp=`git show --format=%ci HEAD | head -n 1` commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./'` diff --git a/scripts/travis-emscripten/publish_binary.sh b/scripts/travis-emscripten/publish_binary.sh index bfdf99065..d372995cf 100755 --- a/scripts/travis-emscripten/publish_binary.sh +++ b/scripts/travis-emscripten/publish_binary.sh @@ -33,7 +33,7 @@ set -e VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_VERSION "\(.*\)".*/\1/') test -n "$VER" VER="v$VER" -COMMIT=$(git rev-parse --short HEAD) +COMMIT=$(git rev-parse --short=8 HEAD) DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%-m.%-d) # remove leading zeros in components - they are not semver-compatible From 3b6e131d852eab0c74260d9ca5c7a11501265da1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Sep 2016 17:34:12 +0200 Subject: [PATCH 15/21] Fix hex check. --- cmake/scripts/buildinfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index e6077a349..8e1615f6d 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -52,7 +52,7 @@ if (NOT SOL_COMMIT_HASH) message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or " "supply a file called commit_hash.txt") endif() -if (NOT SOL_COMMIT_HASH MATCHES [a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]) +if (NOT SOL_COMMIT_HASH MATCHES [a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]) message(FATAL_ERROR "Malformed commit hash \"${SOL_COMMIT_HASH}\". It has to consist of exactly 8 hex digits.") endif() From 031fd568cc753c2ac21e651eaadf2381b2585191 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Sep 2016 18:01:13 +0200 Subject: [PATCH 16/21] Fix crash for TypeName[k]. --- Changelog.md | 8 ++++++++ libsolidity/analysis/TypeChecker.cpp | 2 +- test/libsolidity/SolidityNameAndTypeResolution.cpp | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 1ae186581..d61ac7c83 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,11 @@ +### 0.4.2 + + * Type Checker: Fixed a crash about invalid array types. + +### 0.4.1 (2016-09-09) + + * Build System: Fixes to allow library compilation. + ### 0.4.0 (2016-09-08) This release deliberately breaks backwards compatibility mostly to diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d9c54f755..ae7c13c88 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1438,7 +1438,7 @@ bool TypeChecker::visit(IndexAccess const& _access) length->literalValue(nullptr) )); else - typeError(index->location(), "Integer constant expected."); + fatalTypeError(index->location(), "Integer constant expected."); } break; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 58736025b..b8c643360 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4009,6 +4009,16 @@ BOOST_AUTO_TEST_CASE(external_constructor) BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(invalid_array_as_statement) +{ + char const* text = R"( + contract test { + struct S { uint x; } + function test(uint k) { S[k]; } + } + )"; + BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); +} BOOST_AUTO_TEST_SUITE_END() From 727c6fac85cb5f752525b9f2312707755577162f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Sep 2016 17:44:32 +0200 Subject: [PATCH 17/21] Allow value transfer to library functions. --- Changelog.md | 1 + libsolidity/codegen/ContractCompiler.cpp | 4 +++- test/libsolidity/SolidityEndToEndTest.cpp | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index d61ac7c83..e18d8507b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,6 @@ ### 0.4.2 + * Code Generator: Fix library functions being called from payable functions. * Type Checker: Fixed a crash about invalid array types. ### 0.4.1 (2016-09-09) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 33571bc0f..18b42fce4 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -263,7 +263,9 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration()); m_context << callDataUnpackerEntryPoints.at(it.first); - if (!functionType->isPayable()) + // We have to allow this for libraries, because value of the previous + // call is still visible in the delegatecall. + if (!functionType->isPayable() && !_contract.isLibrary()) { // Throw if function is not payable but call contained ether. m_context << Instruction::CALLVALUE; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 7ee5700c7..3c949e9ac 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7144,6 +7144,23 @@ BOOST_AUTO_TEST_CASE(payable_function) BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27); } +BOOST_AUTO_TEST_CASE(payable_function_calls_library) +{ + char const* sourceCode = R"( + library L { + function f() returns (uint) { return 7; } + } + contract C { + function f() payable returns (uint) { + return L.f(); + } + } + )"; + compileAndRun(sourceCode, 0, "L"); + compileAndRun(sourceCode, 0, "C", bytes(), map{{"L", m_contractAddress}}); + BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_CASE(non_payable_throw) { char const* sourceCode = R"( From dd2f878e594807cb86bdb49bc979c63e2b8d7e81 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 16 Sep 2016 12:56:43 +0200 Subject: [PATCH 18/21] Test case. --- test/libsolidity/SolidityEndToEndTest.cpp | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 7ee5700c7..c8bc7ff91 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7186,6 +7186,33 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier) BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); } +BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) +{ + // This tests that memory resize for return values is not paid during the call, which would + // make the gas calculation overly complex. We access the end of the output area before + // the call is made. + // Tests that this also survivecs the optimizer. + char const* sourceCode = R"( + contract C { + function f() returns (uint[200]) {} + } + contract D { + function f(C c) returns (uint) { c.f(); return 7; } + } + )"; + + compileAndRun(sourceCode, 0, "C"); + u160 cAddr = m_contractAddress; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); + + m_optimize = true; + + compileAndRun(sourceCode, 0, "C"); + u160 cAddrOpt = m_contractAddress; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7))); +} BOOST_AUTO_TEST_SUITE_END() From 5a45990458e9fc39a124d2b949ff77d1f6f1d8a7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 16 Sep 2016 12:56:52 +0200 Subject: [PATCH 19/21] Access output memory area so that we do not pay for resize during call. --- libsolidity/codegen/ExpressionCompiler.cpp | 17 +++++++++++++---- test/libsolidity/SolidityEndToEndTest.cpp | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 96ca42966..26acd8a47 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1476,6 +1476,18 @@ void ExpressionCompiler::appendExternalFunctionCall( utils().storeFreeMemoryPointer(); } + // Touch the end of the output area so that we do not pay for memory resize during the call + // (which we would have to subtract from the gas left) + // We could also just use MLOAD; POP right before the gas calculation, but the optimizer + // would remove that, so we use MSTORE here. + if (!_functionType.gasSet() && retSize > 0) + { + m_context << u256(0); + utils().fetchFreeMemoryPointer(); + // This touches too much, but that way we save some rounding arithmetics + m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE; + } + // Copy function identifier to memory. utils().fetchFreeMemoryPointer(); if (!_functionType.isBareCall() || manualFunctionId) @@ -1551,10 +1563,7 @@ void ExpressionCompiler::appendExternalFunctionCall( gasNeededByCaller += eth::GasCosts::callValueTransferGas; if (!isCallCode && !isDelegateCall && !existenceChecked) gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know - m_context << - gasNeededByCaller << - Instruction::GAS << - Instruction::SUB; + m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB; } if (isDelegateCall) m_context << Instruction::DELEGATECALL; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c8bc7ff91..0ce2851b5 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7191,7 +7191,7 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) // This tests that memory resize for return values is not paid during the call, which would // make the gas calculation overly complex. We access the end of the output area before // the call is made. - // Tests that this also survivecs the optimizer. + // Tests that this also survives the optimizer. char const* sourceCode = R"( contract C { function f() returns (uint[200]) {} From a4f6e5b16c7b9a9ba94c63b6042c20a988219e8e Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 16 Sep 2016 17:03:47 +0200 Subject: [PATCH 20/21] Changelog entry. --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index d61ac7c83..609bb9f8b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,8 @@ ### 0.4.2 * Type Checker: Fixed a crash about invalid array types. + * Code Generator: Fixed a call gas bug that became visible after + version 0.4.0 for calls where the output is larger than the input. ### 0.4.1 (2016-09-09) From 1910e9585d5a39bf2673930d3d7563c25a088513 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 17 Sep 2016 15:04:16 +0200 Subject: [PATCH 21/21] Finished version 0.4.2 --- Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index c438b9147..b5c0631d1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,6 @@ -### 0.4.2 +### 0.4.2 (2016-09-17) + +Bugfixes: * Code Generator: Fix library functions being called from payable functions. * Type Checker: Fixed a crash about invalid array types.