diff options
-rw-r--r-- | .travis.yml | 109 | ||||
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | docs/control-structures.rst | 4 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 3 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 4 | ||||
-rw-r--r-- | libsolidity/analysis/GlobalContext.cpp | 4 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 7 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 8 | ||||
-rw-r--r-- | scripts/Dockerfile | 22 | ||||
-rwxr-xr-x | scripts/docker_deploy.sh | 23 | ||||
-rwxr-xr-x | scripts/install_deps.sh | 37 | ||||
-rwxr-xr-x | scripts/tests.sh | 4 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 19 |
13 files changed, 164 insertions, 81 deletions
diff --git a/.travis.yml b/.travis.yml index b642d947..26e6b214 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ #------------------------------------------------------------------------------ language: cpp + branches: # We need to whitelist the branches which we want to have "push" automation, # this includes tags (which are treated as branches by travis). @@ -33,6 +34,18 @@ branches: - develop - release - /^v[0-9]/ + +env: + global: + - ENCRYPTION_LABEL="6d4541b72666" + - SOLC_BUILD_TYPE=RelWithDebInfo + - SOLC_DOCS=Off + - SOLC_EMSCRIPTEN=Off + - SOLC_INSTALL_DEPS_TRAVIS=On + - SOLC_RELEASE=On + - SOLC_TESTS=On + - SOLC_DOCKER=Off + matrix: include: # Ubuntu 14.04 LTS "Trusty Tahr" @@ -61,10 +74,24 @@ matrix: dist: trusty sudo: required compiler: gcc + before_install: + - sudo apt-get -y install python-sphinx env: - - TRAVIS_DOCS=On - - TRAVIS_RELEASE=Off - - TRAVIS_TESTS=Off + - SOLC_DOCS=On + - SOLC_RELEASE=Off + - SOLC_TESTS=Off + + # Docker target, which generates a statically linked alpine image + - os: linux + dist: trusty + sudo: required + services: + - docker + env: + - SOLC_DOCKER=On + - SOLC_INSTALL_DEPS_TRAVIS=Off + - SOLC_RELEASE=Off + - SOLC_TESTS=Off # Emscripten target, which compiles 'solc' to javascript and uploads the resulting .js # files to https://github.com/ethereum/solc-bin. These binaries are used in Browser-Solidity @@ -73,16 +100,17 @@ matrix: dist: trusty sudo: required compiler: gcc - node_js: "6" + node_js: + - "6" services: - docker before_install: - docker pull trzeci/emscripten:sdk-tag-1.35.4-64bit env: - - TRAVIS_EMSCRIPTEN=On - - TRAVIS_INSTALL_DEPS=Off - - TRAVIS_RELEASE=Off - - TRAVIS_TESTS=Off + - SOLC_EMSCRIPTEN=On + - SOLC_INSTALL_DEPS_TRAVIS=Off + - SOLC_RELEASE=Off + - SOLC_TESTS=Off # OS X Mavericks (10.9) # https://en.wikipedia.org/wiki/OS_X_Mavericks @@ -101,7 +129,7 @@ matrix: # env: # # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" # # https://github.com/ethereum/solidity/issues/894 -# - TRAVIS_TESTS=Off +# - SOLC_TESTS=Off # - ZIP_SUFFIX=osx-yosemite # OS X El Capitan (10.11) @@ -112,10 +140,10 @@ matrix: # env: # # The use of Debug config here ONLY for El Capitan is a workaround for "The Heisenbug" # # See https://github.com/ethereum/webthree-umbrella/issues/565 -# - TRAVIS_BUILD_TYPE=Debug +# - SOLC_BUILD_TYPE=Debug # # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" # # https://github.com/ethereum/solidity/issues/894 -# - TRAVIS_TESTS=Off +# - SOLC_TESTS=Off # - ZIP_SUFFIX=osx-elcapitan # macOS Sierra (10.12) @@ -126,10 +154,10 @@ matrix: # env: # # Look like "The Heisenbug" is occurring here too, so we'll do the same workaround. # # See https://travis-ci.org/ethereum/solidity/jobs/150240930 -# - TRAVIS_BUILD_TYPE=Debug +# - SOLC_BUILD_TYPE=Debug # # Workaround for "macOS - Yosemite, El Capitan and Sierra hanging?" # # https://github.com/ethereum/solidity/issues/894 -# - TRAVIS_TESTS=Off +# - SOLC_TESTS=Off # - ZIP_SUFFIX=macos-sierra git: @@ -143,37 +171,20 @@ cache: - $HOME/.local install: - - test $TRAVIS_INSTALL_DEPS != On || ./scripts/install_deps.sh - - test "$TRAVIS_OS_NAME" != "linux" || ./scripts/install_cmake.sh + - test $SOLC_INSTALL_DEPS_TRAVIS != On || (scripts/install_deps.sh) + - test "$TRAVIS_OS_NAME" != "linux" || (scripts/install_cmake.sh) - echo -n "$TRAVIS_COMMIT" > commit_hash.txt + - test $SOLC_DOCKER != On || (docker build -t ethereum/solc:build -f scripts/Dockerfile .) + before_script: - - test $TRAVIS_EMSCRIPTEN != On || ./scripts/build_emscripten.sh - - test $TRAVIS_RELEASE != On || (./scripts/build.sh $TRAVIS_BUILD_TYPE - && ./scripts/release.sh $ZIP_SUFFIX - && ./scripts/create_source_tarball.sh ) -script: - - test $TRAVIS_DOCS != On || ./scripts/docs.sh + - test $SOLC_EMSCRIPTEN != On || (scripts/build_emscripten.sh) + - test $SOLC_RELEASE != On || (scripts/build.sh $SOLC_BUILD_TYPE + && scripts/release.sh $ZIP_SUFFIX + && scripts/create_source_tarball.sh) - # There are a variety of reliability issues with the Solidity unit-tests at the time of - # writing (especially on macOS), so within TravisCI we will try to run the unit-tests - # up to 3 times before giving up and declaring the tests as broken. - # - # We should aim to remove this "retry logic" as soon as we can, because it is a - # band-aid for issues which need solving at their root. Some of those issues will be - # in Solidity's RPC setup and some will be in 'eth'. It seems unlikely that Solidity - # itself is broken from the failure messages which we are seeing. - # - # More details on known issues at https://github.com/ethereum/solidity/issues/769 - - test $TRAVIS_TESTS != On || (cd $TRAVIS_BUILD_DIR && (./scripts/tests.sh || ./scripts/tests.sh || ./scripts/tests.sh) ) -env: - global: - - ENCRYPTION_LABEL="6d4541b72666" - - TRAVIS_BUILD_TYPE=RelWithDebInfo - - TRAVIS_DOCS=Off - - TRAVIS_EMSCRIPTEN=Off - - TRAVIS_INSTALL_DEPS=On - - TRAVIS_RELEASE=On - - TRAVIS_TESTS=On +script: + - test $SOLC_DOCS != On || (scripts/docs.sh) + - test $SOLC_TESTS != On || (cd $TRAVIS_BUILD_DIR && scripts/tests.sh) deploy: # This is the deploy target for the Emscripten build. @@ -182,14 +193,24 @@ deploy: # Both the build and deploy steps for Emscripten are only run within the Ubuntu # configurations (not for macOS). That is controlled by conditionals within the bash # scripts because TravisCI doesn't provide much in the way of conditional logic. + - provider: script - script: test $TRAVIS_EMSCRIPTEN != On || scripts/release_emscripten.sh + script: test $SOLC_EMSCRIPTEN != On || (scripts/release_emscripten.sh) + skip_cleanup: true + on: + branch: + - develop + - release + # This is the deploy target for the dockerfile. If we are pushing into a develop branch, it will be tagged + # as a nightly and appended the commit of the branch it was pushed in. If we are pushing to master it will + # be tagged as "stable" and given the version tag as well. + - provider: script + script: test $SOLC_DOCKER != On || (scripts/docker_deploy.sh) skip_cleanup: true on: branch: - develop - release - # This is the deploy target for the native build (Linux and macOS) # which generates ZIPs per commit and the source tarball. # @@ -207,4 +228,4 @@ deploy: on: all_branches: true tags: true - condition: $TRAVIS_RELEASE == On + condition: $SOLC_RELEASE == On diff --git a/Changelog.md b/Changelog.md index 0c4e8329..d383ba42 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.10 (unreleased) Features: + * Add ``assert(condition)``, which throws if condition is false. * Type system: Support explicit conversion of external function to address. Bugfixes: diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 1c7d71f2..ff0a48ec 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -396,6 +396,10 @@ Currently, Solidity automatically generates a runtime exception in the following #. If your contract receives Ether via a public getter function. #. If you call a zero-initialized variable of internal function type. +While a user-provided exception is generated in the following situations: +#. Calling ``throw``. +#. The condition of ``assert(condition)`` is not met. + Internally, Solidity performs an "invalid jump" when a user-provided exception is thrown. In contrast, it performs an invalid operation (instruction ``0xfe``) if a runtime exception is encountered. In both cases, this causes the EVM to revert all changes made to the state. The reason for this is that there is no safe way to continue execution, because an expected effect diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 47650067..a64ceeb2 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -435,7 +435,7 @@ The following is the order of precedence for operators, listed in order of evalu | *16* | Comma operator | ``,`` | +------------+-------------------------------------+--------------------------------------------+ -.. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send +.. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, assert, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send Global Variables ================ @@ -460,6 +460,7 @@ Global Variables - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256`` - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256`` +- ``assert(bool condition)``: throws if the condition is false - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` - ``super``: the contract one level higher in the inheritance hierarchy - ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index dd3d4be8..a6f6613f 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -79,11 +79,13 @@ Block and Transaction Properties You can only access the hashes of the most recent 256 blocks, all other values will be zero. -.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send +.. index:: assert, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send Mathematical and Cryptographic Functions ---------------------------------------- +``assert(bool condition)``: + throws if the condition is not met. ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. ``mulmod(uint x, uint y, uint k) returns (uint)``: diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index e46868be..cc418c5e 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -65,7 +65,9 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared< make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)), make_shared<MagicVariableDeclaration>("ripemd160", - make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true))}) + make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true)), + make_shared<MagicVariableDeclaration>("assert", + make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Location::Assert))}) { } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index e280b32c..83d840e0 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -819,8 +819,8 @@ public: { Internal, ///< stack-call using plain JUMP External, ///< external call using CALL - CallCode, ///< extercnal call using CALLCODE, i.e. not exchanging the storage - DelegateCall, ///< extercnal call using DELEGATECALL, i.e. not exchanging the storage + CallCode, ///< external call using CALLCODE, i.e. not exchanging the storage + DelegateCall, ///< external call using DELEGATECALL, i.e. not exchanging the storage Bare, ///< CALL without function hash BareCallCode, ///< CALLCODE without function hash BareDelegateCall, ///< DELEGATECALL without function hash @@ -844,7 +844,8 @@ public: MulMod, ///< MULMOD ArrayPush, ///< .push() to a dynamically sized array in storage ByteArrayPush, ///< .push() to a dynamically sized byte array in storage - ObjectCreation ///< array creation using new + ObjectCreation, ///< array creation using new + Assert ///< assert() }; virtual Category category() const override { return Category::Function; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index d74d9dd3..f69d61db 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -863,6 +863,14 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << Instruction::POP; break; } + case Location::Assert: + { + arguments.front()->accept(*this); + utils().convertType(*arguments.front()->annotation().type, *function.parameterTypes().front(), false); + m_context << Instruction::ISZERO; + m_context.appendConditionalJumpTo(m_context.errorTag()); + break; + } default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid function type.")); } diff --git a/scripts/Dockerfile b/scripts/Dockerfile index e34436ed..8be19783 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -1,12 +1,16 @@ FROM alpine MAINTAINER chriseth <chris@ethereum.org> +#Official solidity docker image -RUN \ - apk --no-cache --update add build-base cmake boost-dev git && \ - sed -i -E -e 's/include <sys\/poll.h>/include <poll.h>/' /usr/include/boost/asio/detail/socket_types.hpp && \ - git clone --depth 1 --recursive -b develop https://github.com/ethereum/solidity && \ - cd /solidity && cmake -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSTATIC_LINKING=1 && \ - cd /solidity && make solc && install -s solc/solc /usr/bin && \ - cd / && rm -rf solidity && \ - apk del sed build-base git make cmake gcc g++ musl-dev curl-dev boost-dev && \ - rm -rf /var/cache/apk/* +#Establish working directory as solidity +WORKDIR /solidity +#Copy working directory on travis to the image +COPY / $WORKDIR + +#Install dependencies, eliminate annoying warnings, and build release, delete all remaining points and statically link. +RUN ./scripts/install_deps.sh && sed -i -E -e 's/include <sys\/poll.h>/include <poll.h>/' /usr/include/boost/asio/detail/socket_types.hpp &&\ +cmake -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSTATIC_LINKING=1 &&\ +make solc && install -s solc/solc /usr/bin &&\ +cd / && rm -rf solidity &&\ +apk del sed build-base git make cmake gcc g++ musl-dev curl-dev boost-dev &&\ +rm -rf /var/cache/apk/*
\ No newline at end of file diff --git a/scripts/docker_deploy.sh b/scripts/docker_deploy.sh new file mode 100755 index 00000000..d2810a3e --- /dev/null +++ b/scripts/docker_deploy.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +set -e + +docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; +version=$(grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? $(dirname "$0")/../CMakeLists.txt) +if [ "$TRAVIS_BRANCH" = "develop" ] +then + docker tag ethereum/solc:build ethereum/solc:nightly; + docker tag ethereum/solc:build ethereum/solc:nightly-"$version"-"$TRAVIS_COMMIT" + docker push ethereum/solc:nightly-"$version"-"$TRAVIS_COMMIT"; + docker push ethereum/solc:nightly; +elif [ "$TRAVIS_BRANCH" = "release" ] +then + docker tag ethereum/solc:build ethereum/solc:stable; + docker push ethereum/solc:stable; +elif [ "$TRAVIS_TAG" = v"$version" ] +then + docker tag ethereum/solc:build ethereum/solc:"$version"; + docker push ethereum/solc:"$version"; +else + echo "Not publishing docker image from branch $TRAVIS_BRANCH or tag $TRAVIS_TAG" +fi diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index f21c48d0..7cfc92f2 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -57,7 +57,7 @@ detect_linux_distro() { # 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 + DISTRO=CentOS else DISTRO='' fi @@ -93,19 +93,17 @@ case $(uname -s) in # Check for Homebrew install and abort if it is not installed. brew -v > /dev/null 2>&1 || { echo >&2 "ERROR - solidity requires a Homebrew install. See http://brew.sh."; exit 1; } - brew update - brew upgrade - brew install boost brew install cmake - - # We should really 'brew install' our eth client here, but at the time of writing - # the bottle is known broken, so we will just cheat and use a hardcoded ZIP for - # the time being, which is good enough. The cause of the breaks will go away - # when we commit the repository reorg changes anyway. - curl -L -O https://github.com/bobsummerwill/cpp-ethereum/releases/download/v1.3.0/cpp-ethereum-osx-mavericks-v1.3.0.zip - unzip cpp-ethereum-osx-mavericks-v1.3.0.zip + if ["$CI" = true]; then + brew upgrade cmake + brew tap ethereum/ethereum + brew install cpp-ethereum + brew linkapps cpp-ethereum + else + brew upgrade + fi ;; @@ -207,7 +205,6 @@ case $(uname -s) in # Install "normal packages" sudo apt-get -y update sudo apt-get -y install \ - python-sphinx \ build-essential \ cmake \ g++ \ @@ -311,17 +308,17 @@ case $(uname -s) in sudo apt-get -y update sudo apt-get -y install \ - python-sphinx \ build-essential \ cmake \ git \ libboost-all-dev - - # Install 'eth', for use in the Solidity Tests-over-IPC. - sudo add-apt-repository -y ppa:ethereum/ethereum - sudo add-apt-repository -y ppa:ethereum/ethereum-dev - sudo apt-get -y update - sudo apt-get -y install eth + if [ "$CI" = true ]; then + # Install 'eth', for use in the Solidity Tests-over-IPC. + sudo add-apt-repository -y ppa:ethereum/ethereum + sudo add-apt-repository -y ppa:ethereum/ethereum-dev + sudo apt-get -y update + sudo apt-get -y install eth + fi ;; @@ -397,4 +394,4 @@ case $(uname -s) in echo "If you would like to get your operating system working, that would be fantastic." echo "Drop us a message at https://gitter.im/ethereum/solidity." ;; -esac +esac
\ No newline at end of file diff --git a/scripts/tests.sh b/scripts/tests.sh index 8edfda0b..88815f5f 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -58,7 +58,7 @@ $ETH_PATH --test -d /tmp/test & # is available and is ready for the unit-tests to start talking to it. while [ ! -S /tmp/test/geth.ipc ]; do sleep 2; done echo "--> IPC available." - +sleep 2 # And then run the Solidity unit-tests (once without optimization, once with), # pointing to that IPC endpoint. echo "--> Running tests without optimizer..." @@ -69,4 +69,4 @@ ERROR_CODE=$? pkill eth || true sleep 4 pgrep eth && pkill -9 eth || true -exit $ERROR_CODE +exit $ERROR_CODE
\ No newline at end of file diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 53b61450..ad045881 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9083,6 +9083,25 @@ BOOST_AUTO_TEST_CASE(invalid_instruction) BOOST_CHECK(callContractFunction("f()") == encodeArgs()); } +BOOST_AUTO_TEST_CASE(assert) +{ + char const* sourceCode = R"( + contract C { + function f() { + assert(false); + } + function g(bool val) returns (bool) { + assert(val == true); + return true; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs()); + BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs()); + BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(true)); +} + BOOST_AUTO_TEST_SUITE_END() } |