diff options
-rw-r--r-- | Changelog.md | 2 | ||||
-rw-r--r-- | docs/index.rst | 64 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 7 | ||||
-rw-r--r-- | scripts/Dockerfile_alpine | 5 | ||||
-rwxr-xr-x | scripts/docker_build.sh | 4 | ||||
-rwxr-xr-x | scripts/docker_deploy.sh | 24 | ||||
-rwxr-xr-x | scripts/docker_deploy_manual.sh | 27 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 16 | ||||
-rw-r--r-- | test/libsolidity/SMTCheckerJSONTest.cpp | 87 |
9 files changed, 142 insertions, 94 deletions
diff --git a/Changelog.md b/Changelog.md index f5817771..b67bc592 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Compiler Features: Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. + * Commandline interface: Fix crash when using ``--ast`` on empty runtime code. * Code Generator: Annotate jump from calldata decoder to function as "jump in". * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. @@ -23,6 +24,7 @@ Bugfixes: Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. + * Docker: Includes both Scratch and Alpine images. diff --git a/docs/index.rst b/docs/index.rst index 17abf4b2..ed931163 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -19,26 +19,43 @@ user-defined types among other features. With Solidity you can create contracts for uses such as voting, crowdfunding, blind auctions, and multi-signature wallets. -.. note:: - The best way to try out Solidity right now is using - `Remix <https://remix.ethereum.org/>`_ - (it can take a while to load, please be patient). Remix is a web browser - based IDE that allows you to write Solidity smart contracts, then deploy - and run the smart contracts. +Language Documentation +---------------------- + +If you are new to the concept of smart contracts we recommend you start with +:ref:`an example smart contract <simple-smart-contract>` written +in Solidity. When you are ready for more detail, we recommend you read the +:doc:`"Solidity by Example" <solidity-by-example>` and :doc:`"Solidity in Depth" <solidity-in-depth>` sections to learn the core concepts of the language. + +For further reading, try :ref:`the basics of blockchains <blockchain-basics>` +and details of the :ref:`Ethereum Virtual Machine <the-ethereum-virtual-machine>`. + +.. hint:: + You can always try out code examples in your browser with the + `Remix IDE <https://remix.ethereum.org>`_. Remix is a web browser based IDE + that allows you to write Solidity smart contracts, then deploy and run the + smart contracts. It can take a while to load, so please be patient. .. warning:: - Since software is written by humans, it can have bugs. Thus, also - smart contracts should be created following well-known best-practices in - software development. This includes code review, testing, audits and correctness proofs. - Also note that users are sometimes more confident in code than its authors. - Finally, blockchains have their own things to watch out for, so please take - a look at the section :ref:`security_considerations`. + As humans write software, it can have bugs. You should follow established + software development best-practices when writing your smart contracts, this + includes code review, testing, audits, and correctness proofs. Smart contract + users are sometimes more confident with code than their authors, and + blockchains and smart contracts have their own unique issues to + watch out for, so before working on production code, make sure you read the + :ref:`security_considerations` section. + +If you have any questions, you can try searching for answers or asking on the +`Ethereum Stackexchange <https://ethereum.stackexchange.com/>`_, or our `gitter channel <https://gitter.im/ethereum/solidity/>`_. + +Ideas for improving Solidity or this documentation are always welcome, read our :doc:`contributors guide <contributing>` for more details. Translations ------------ -This documentation is translated into several languages by community volunteers -with varying degrees of completeness and up-to-dateness. The English version stands as a reference. +Community volunteers help translate this documentation into several languages. +They have varying degrees of completeness and up-to-dateness. The English +version stands as a reference. * `Simplified Chinese <http://solidity-cn.readthedocs.io>`_ (in progress) * `Spanish <https://solidity-es.readthedocs.io>`_ @@ -46,25 +63,6 @@ with varying degrees of completeness and up-to-dateness. The English version sta * `Korean <http://solidity-kr.readthedocs.io>`_ (in progress) * `French <http://solidity-fr.readthedocs.io>`_ (in progress) -Language Documentation ----------------------- - -On the next pages, we will first see a :ref:`simple smart contract <simple-smart-contract>` written -in Solidity followed by the basics about :ref:`blockchains <blockchain-basics>` -and the :ref:`Ethereum Virtual Machine <the-ethereum-virtual-machine>`. - -The next section will explain several *features* of Solidity by giving -useful :ref:`example contracts <voting>`. -Remember that you can always try out the contracts -`in your browser <https://remix.ethereum.org>`_! - -The fourth and most extensive section will cover all aspects of Solidity in depth. - -If you still have questions, you can try searching or asking on the -`Ethereum Stackexchange <https://ethereum.stackexchange.com/>`_ -site, or come to our `gitter channel <https://gitter.im/ethereum/solidity/>`_. -Ideas for improving Solidity or this documentation are always welcome! - Contents ======== diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 6d5d5cb7..e1a89dd4 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -784,15 +784,10 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) ) m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces."); - // Variables can be declared without type (with "var"), in which case the first assignment - // sets the type. - // Note that assignments before the first declaration are legal because of the special scoping - // rules inherited from JavaScript. - // type is filled either by ReferencesResolver directly from the type name or by // TypeChecker at the VariableDeclarationStatement level. TypePointer varType = _variable.annotation().type; - solAssert(!!varType, "Failed to infer variable type."); + solAssert(!!varType, "Variable type not provided."); if (_variable.value()) expectType(*_variable.value(), *varType); diff --git a/scripts/Dockerfile_alpine b/scripts/Dockerfile_alpine new file mode 100644 index 00000000..21bba456 --- /dev/null +++ b/scripts/Dockerfile_alpine @@ -0,0 +1,5 @@ +FROM alpine +MAINTAINER chriseth <chris@ethereum.org> + +COPY upload/solc-static-linux /usr/local/bin/solc +ENTRYPOINT ["/usr/local/bin/solc"] diff --git a/scripts/docker_build.sh b/scripts/docker_build.sh index 22657a8c..9eedec34 100755 --- a/scripts/docker_build.sh +++ b/scripts/docker_build.sh @@ -2,7 +2,11 @@ set -e +# Scratch image docker build -t ethereum/solc:build -f scripts/Dockerfile . tmp_container=$(docker create ethereum/solc:build sh) mkdir -p upload docker cp ${tmp_container}:/usr/bin/solc upload/solc-static-linux + +# Alpine image +docker build -t ethereum/solc:build-alpine -f scripts/Dockerfile_alpine . diff --git a/scripts/docker_deploy.sh b/scripts/docker_deploy.sh index 00705725..36e918cf 100755 --- a/scripts/docker_deploy.sh +++ b/scripts/docker_deploy.sh @@ -2,20 +2,28 @@ set -e +image="ethereum/solc" + +tag_and_push() +{ + docker tag "$image:$1" "$image:$2" + docker push "$image:$2" +} + docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; version=$($(dirname "$0")/get_version.sh) 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; + tag_and_push build nightly + tag_and_push build nightly-"$version"-"$TRAVIS_COMMIT" + tag_and_push build-alpine nightly-alpine + tag_and_push build-alpine nightly-alpine-"$version"-"$TRAVIS_COMMIT" elif [ "$TRAVIS_TAG" = v"$version" ] then - docker tag ethereum/solc:build ethereum/solc:stable; - docker tag ethereum/solc:build ethereum/solc:"$version"; - docker push ethereum/solc:stable; - docker push ethereum/solc:"$version"; + tag_and_push build stable + tag_and_push build "$version" + tag_and_push build-alpine stable-alpine + tag_and_push build-alpine "$version"-alpine else echo "Not publishing docker image from branch $TRAVIS_BRANCH or tag $TRAVIS_TAG" fi diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index c098f4ee..0393d22d 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -7,6 +7,7 @@ then echo "Usage: $0 <tag/branch>" exit 1 fi +image="ethereum/solc" branch="$1" #docker login @@ -27,21 +28,27 @@ else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt fi +tag_and_push() +{ + docker tag "$image:$1" "$image:$2" + docker push "$image:$2" +} + rm -rf .git -docker build -t ethereum/solc:build -f scripts/Dockerfile . -tmp_container=$(docker create ethereum/solc:build sh) +docker build -t "$image":build -f scripts/Dockerfile . +tmp_container=$(docker create "$image":build sh) if [ "$branch" = "develop" ] then - docker tag ethereum/solc:build ethereum/solc:nightly; - docker tag ethereum/solc:build ethereum/solc:nightly-"$version"-"$commithash" - docker push ethereum/solc:nightly-"$version"-"$commithash"; - docker push ethereum/solc:nightly; + tag_and_push build nightly + tag_and_push build nightly-"$version"-"$commithash" + tag_and_push build-alpine nightly-alpine + tag_and_push build-alpine nightly-alpine-"$version"-"$commithash" elif [ "$branch" = v"$version" ] then - docker tag ethereum/solc:build ethereum/solc:stable; - docker tag ethereum/solc:build ethereum/solc:"$version"; - docker push ethereum/solc:stable; - docker push ethereum/solc:"$version"; + tag_and_push build stable + tag_and_push build "$version" + tag_and_push build-alpine stable-alpine + tag_and_push build-alpine "$version"-alpine else echo "Not publishing docker image from branch or tag $branch" fi diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 7f64d8ac..e2baca7f 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -1022,12 +1022,16 @@ void CommandLineInterface::handleAst(string const& _argStr) map<ASTNode const*, eth::GasMeter::GasConsumption> gasCosts; for (auto const& contract : m_compiler->contractNames()) { - auto ret = GasEstimator::breakToStatementLevel( - GasEstimator(m_evmVersion).structuralEstimation(*m_compiler->runtimeAssemblyItems(contract), asts), - asts - ); - for (auto const& it: ret) - gasCosts[it.first] += it.second; + if (auto const* assemblyItems = m_compiler->runtimeAssemblyItems(contract)) + { + auto ret = GasEstimator::breakToStatementLevel( + GasEstimator(m_evmVersion).structuralEstimation(*assemblyItems, asts), + asts + ); + for (auto const& it: ret) + gasCosts[it.first] += it.second; + } + } bool legacyFormat = !m_args.count(g_argAstCompactJson); diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp index 6e1329a9..e9204cc4 100644 --- a/test/libsolidity/SMTCheckerJSONTest.cpp +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -38,11 +38,15 @@ using namespace boost::unit_test; SMTCheckerTest::SMTCheckerTest(string const& _filename) : SyntaxTest(_filename) { - BOOST_REQUIRE_MESSAGE(boost::algorithm::ends_with(_filename, ".sol"), "Invalid test contract file name: \"" + _filename + "\"."); + if (!boost::algorithm::ends_with(_filename, ".sol")) + BOOST_THROW_EXCEPTION(runtime_error("Invalid test contract file name: \"" + _filename + "\".")); string jsonFilename = _filename.substr(0, _filename.size() - 4) + ".json"; - BOOST_CHECK(jsonParseFile(jsonFilename, m_smtResponses)); - BOOST_CHECK(m_smtResponses.isObject()); + if ( + !jsonParseFile(jsonFilename, m_smtResponses) || + !m_smtResponses.isObject() + ) + BOOST_THROW_EXCEPTION(runtime_error("Invalid JSON file.")); } bool SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) @@ -59,42 +63,62 @@ bool SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool const // This is the list of responses provided in the test string auxInput("auxiliaryInput"); - BOOST_CHECK(m_smtResponses.isMember(auxInput)); + if (!m_smtResponses.isMember(auxInput)) + BOOST_THROW_EXCEPTION(runtime_error("JSON file does not contain field \"auxiliaryInput\".")); + vector<string> inHashes = hashesFromJson(m_smtResponses, auxInput, "smtlib2responses"); // Ensure that the provided list matches the requested one - BOOST_CHECK_MESSAGE( - outHashes == inHashes, - "SMT query hashes differ: " + boost::algorithm::join(outHashes, ", ") + " x " + boost::algorithm::join(inHashes, ", ") - ); + if (outHashes != inHashes) + BOOST_THROW_EXCEPTION(runtime_error( + "SMT query hashes differ: " + + boost::algorithm::join(outHashes, ", ") + + " x " + + boost::algorithm::join(inHashes, ", ") + )); // Rerun the compiler with the provided hashed (2nd run) input[auxInput] = m_smtResponses[auxInput]; Json::Value endResult = compiler.compile(input); - BOOST_CHECK(endResult.isMember("errors")); - Json::Value const& errors = endResult["errors"]; - for (auto const& error: errors) + if (endResult.isMember("errors") && endResult["errors"].isArray()) { - BOOST_CHECK(error.isMember("type") && error["type"].isString()); - BOOST_CHECK(error.isMember("message") && error["message"].isString()); - if (!error.isMember("sourceLocation")) - continue; - Json::Value const& location = error["sourceLocation"]; - BOOST_CHECK(location.isMember("start") && location["start"].isInt()); - BOOST_CHECK(location.isMember("end") && location["end"].isInt()); - int start = location["start"].asInt(); - int end = location["end"].asInt(); - if (start >= static_cast<int>(versionPragma.size())) - start -= versionPragma.size(); - if (end >= static_cast<int>(versionPragma.size())) - end -= versionPragma.size(); - m_errorList.emplace_back(SyntaxTestError{ - error["type"].asString(), - error["message"].asString(), - start, - end - }); + Json::Value const& errors = endResult["errors"]; + for (auto const& error: errors) + { + if ( + !error.isMember("type") || + !error["type"].isString() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a type.")); + if ( + !error.isMember("message") || + !error["message"].isString() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a message.")); + if (!error.isMember("sourceLocation")) + continue; + Json::Value const& location = error["sourceLocation"]; + if ( + !location.isMember("start") || + !location["start"].isInt() || + !location.isMember("end") || + !location["end"].isInt() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a SourceLocation with start and end.")); + int start = location["start"].asInt(); + int end = location["end"].asInt(); + if (start >= static_cast<int>(versionPragma.size())) + start -= versionPragma.size(); + if (end >= static_cast<int>(versionPragma.size())) + end -= versionPragma.size(); + m_errorList.emplace_back(SyntaxTestError{ + error["type"].asString(), + error["message"].asString(), + start, + end + }); + } } return printExpectationAndError(_stream, _linePrefix, _formatted); @@ -123,6 +147,7 @@ Json::Value SMTCheckerTest::buildJson(string const& _extra) string sources = " \"sources\": { " + sourceName + ": " + sourceObj + "}"; string input = "{" + language + ", " + sources + "}"; Json::Value source; - BOOST_REQUIRE(jsonParse(input, source)); + if (!jsonParse(input, source)) + BOOST_THROW_EXCEPTION(runtime_error("Could not build JSON from string.")); return source; } |