From b0af628f11168b00d1f900f96844466dfcdc72f1 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 10 Dec 2014 23:01:40 +0100 Subject: [PATCH 01/10] Calls to bare contracts. --- libsolidity/ExpressionCompiler.cpp | 122 ++++++++++++++++------------- libsolidity/ExpressionCompiler.h | 20 +++++ libsolidity/Types.cpp | 7 ++ libsolidity/Types.h | 3 +- 4 files changed, 95 insertions(+), 57 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 3beb423de..add5f73be 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -194,7 +194,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { FunctionType const& function = dynamic_cast(*_functionCall.getExpression().getType()); - std::vector> arguments = _functionCall.getArguments(); + vector> arguments = _functionCall.getArguments(); if (asserts(arguments.size() == function.getParameterTypes().size())) BOOST_THROW_EXCEPTION(InternalCompilerError()); @@ -227,50 +227,23 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; } case Location::EXTERNAL: + case Location::BARE: { - unsigned dataOffset = 1; // reserve one byte for the function index - for (unsigned i = 0; i < arguments.size(); ++i) - { - arguments[i]->accept(*this); - Type const& type = *function.getParameterTypes()[i]; - appendTypeConversion(*arguments[i]->getType(), type); - unsigned const numBytes = type.getCalldataEncodedSize(); - if (numBytes == 0 || numBytes > 32) - BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_sourceLocation(arguments[i]->getLocation()) - << errinfo_comment("Type " + type.toString() + " not yet supported.")); - bool const leftAligned = type.getCategory() == Type::Category::STRING; - CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned); - dataOffset += numBytes; - } - //@todo only return the first return value for now - Type const* firstType = function.getReturnParameterTypes().empty() ? nullptr : - function.getReturnParameterTypes().front().get(); - unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; - // CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top) - m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0) << u256(0); - _functionCall.getExpression().accept(*this); // pushes addr and function index - m_context << u256(0) << eth::Instruction::MSTORE8 - << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB - << eth::Instruction::CALL - << eth::Instruction::POP; // @todo do not ignore failure indicator - if (retSize > 0) - { - bool const leftAligned = firstType->getCategory() == Type::Category::STRING; - CompilerUtils(m_context).loadFromMemory(0, retSize, leftAligned); - } + FunctionCallOptions options; + options.bare = function.getLocation() == Location::BARE; + options.obtainAddress = [&]() { _functionCall.getExpression().accept(*this); }; + appendExternalFunctionCall(function, arguments, options); break; } case Location::SEND: - m_context << u256(0) << u256(0) << u256(0) << u256(0); - arguments.front()->accept(*this); - //@todo might not be necessary - appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); - _functionCall.getExpression().accept(*this); - m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB - << eth::Instruction::CALL - << eth::Instruction::POP; + { + FunctionCallOptions options; + options.bare = true; + options.obtainAddress = [&]() { _functionCall.getExpression().accept(*this); }; + options.obtainValue = [&]() { arguments.front()->accept(*this); }; + appendExternalFunctionCall(FunctionType({}, {}, Location::EXTERNAL), {}, options); break; + } case Location::SUICIDE: arguments.front()->accept(*this); //@todo might not be necessary @@ -292,19 +265,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) {Location::SHA256, 2}, {Location::RIPEMD160, 3}}; u256 contractAddress = contractAddresses.find(function.getLocation())->second; - // @todo later, combine this code with external function call - for (unsigned i = 0; i < arguments.size(); ++i) - { - arguments[i]->accept(*this); - appendTypeConversion(*arguments[i]->getType(), *function.getParameterTypes()[i], true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(i * 32); - } - m_context << u256(32) << u256(0) << u256(arguments.size() * 32) << u256(0) << u256(0) - << contractAddress << u256(500) //@todo determine actual gas requirement - << eth::Instruction::CALL - << eth::Instruction::POP; - CompilerUtils(m_context).loadFromMemory(0); + FunctionCallOptions options; + options.bare = true; + options.obtainAddress = [&]() { m_context << contractAddress; }; + options.packDensely = false; + appendExternalFunctionCall(function, arguments, options); break; } default: @@ -326,11 +291,9 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::ADDRESS), true); m_context << eth::Instruction::BALANCE; } - else if (member == "send") - { + else if (member == "send" || member.substr(0, 4) == "call") appendTypeConversion(*_memberAccess.getExpression().getType(), IntegerType(0, IntegerType::Modifier::ADDRESS), true); - } else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer.")); break; @@ -587,6 +550,53 @@ void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND; } +void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functionType, + vector> const& _arguments, + FunctionCallOptions const& _options) +{ + if (asserts(_arguments.size() == _functionType.getParameterTypes().size())) + BOOST_THROW_EXCEPTION(InternalCompilerError()); + + unsigned dataOffset = _options.bare ? 0 : 1; // reserve one byte for the function index + for (unsigned i = 0; i < _arguments.size(); ++i) + { + _arguments[i]->accept(*this); + Type const& type = *_functionType.getParameterTypes()[i]; + appendTypeConversion(*_arguments[i]->getType(), type); + unsigned const numBytes = _options.packDensely ? type.getCalldataEncodedSize() : 32; + if (numBytes == 0 || numBytes > 32) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_arguments[i]->getLocation()) + << errinfo_comment("Type " + type.toString() + " not yet supported.")); + bool const leftAligned = type.getCategory() == Type::Category::STRING; + CompilerUtils(m_context).storeInMemory(dataOffset, numBytes, leftAligned); + dataOffset += numBytes; + } + //@todo only return the first return value for now + Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : + _functionType.getReturnParameterTypes().front().get(); + unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; + if (!_options.packDensely && retSize > 0) + retSize = 32; + // CALL arguments: outSize, outOff, inSize, inOff, value, addr, gas (stack top) + m_context << u256(retSize) << u256(0) << u256(dataOffset) << u256(0); + if (_options.obtainValue) + _options.obtainValue(); + else + m_context << u256(0); + _options.obtainAddress(); + if (!_options.bare) + m_context << u256(0) << eth::Instruction::MSTORE8; + m_context << u256(25) << eth::Instruction::GAS << eth::Instruction::SUB + << eth::Instruction::CALL + << eth::Instruction::POP; // @todo do not ignore failure indicator + if (retSize > 0) + { + bool const leftAligned = firstType->getCategory() == Type::Category::STRING; + CompilerUtils(m_context).loadFromMemory(0, retSize, leftAligned); + } +} + ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, unsigned _baseStackOffset): m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset), diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index c0b173d46..0bba211ce 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -20,6 +20,7 @@ * Solidity AST to EVM bytecode compiler for expressions. */ +#include #include #include #include @@ -83,6 +84,25 @@ private: //// Appends code that cleans higher-order bits for integer types. void appendHighBitsCleanup(IntegerType const& _typeOnStack); + /// Additional options used in appendExternalFunctionCall. + struct FunctionCallOptions + { + FunctionCallOptions() {} + /// Invoked to copy the address to the stack + std::function obtainAddress; + /// Invoked to copy the ethe value to the stack (if not specified, value is 0). + std::function obtainValue; + /// If true, do not prepend function index to call data + bool bare = false; + /// If false, use calling convention that all arguments and return values are packed as + /// 32 byte values with padding. + bool packDensely = true; + }; + + /// Appends code to call a function of the given type with the given arguments. + void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, + FunctionCallOptions const& _options = FunctionCallOptions()); + /** * Helper class to store and retrieve lvalues to and from various locations. * All types except STACK store a reference in a slot on the stack, STACK just diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 00e530c3f..a0a809b9b 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -194,6 +194,11 @@ u256 IntegerType::literalValue(Literal const& _literal) const const MemberList IntegerType::AddressMemberList = MemberList({{"balance", make_shared(256)}, + {"callstring32", make_shared(TypePointers({make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"callstring32string32", make_shared(TypePointers({make_shared(32), + make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, {"send", make_shared(TypePointers({make_shared(256)}), TypePointers(), FunctionType::Location::SEND)}}); @@ -424,6 +429,8 @@ unsigned FunctionType::getSizeOnStack() const return 1; case Location::EXTERNAL: return 2; + case Location::BARE: + return 1; default: return 0; } diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 8e93bd31d..807e60c74 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -296,8 +296,9 @@ class FunctionType: public Type public: /// The meaning of the value(s) on the stack referencing the function: /// INTERNAL: jump tag, EXTERNAL: contract address + function index, + /// BARE: contract address (non-abi contract call) /// OTHERS: special virtual function, nothing on the stack - enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160 }; + enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, BARE }; virtual Category getCategory() const override { return Category::FUNCTION; } explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); From 1e80a16ec84e83d9176506a2a9ca4091dc6d0f03 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sat, 13 Dec 2014 23:46:20 +0100 Subject: [PATCH 02/10] fixed macdeplyqt path on macos --- cmake/EthDependencies.cmake | 11 +++++++++++ cmake/EthExecutableHelper.cmake | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 24e5bd07d..ee93a5311 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -17,6 +17,11 @@ if (WIN32) #set (CMAKE_PREFIX_PATH "C:/Program Files/Windows Kits/8.1/Lib/winv6.3/um/x64") endif() +# homebrew installs qts in opt +if (APPLE) + set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/qt5") +endif() + # Dependencies must have a version number, to ensure reproducible build. The version provided here is the one that is in the extdep repository. If you use system libraries, version numbers may be different. find_package (CryptoPP 5.6.2 EXACT REQUIRED) @@ -102,6 +107,12 @@ if (NOT HEADLESS) find_package (Qt5WebKit REQUIRED) find_package (Qt5WebKitWidgets REQUIRED) + # we need to find path to macdeployqt on mac + if (APPLE) + set (MACDEPLOYQT_APP ${Qt5Core_DIR}/../../../bin/macdeployqt) + message(" - macdeployqt path: ${MACDEPLOYQT_APP}") + endif() + endif() #HEADLESS # use multithreaded boost libraries, with -mt suffix diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index adda57692..56aa3f6c3 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -66,7 +66,7 @@ macro(eth_install_executable EXECUTABLE) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${ETH_DEPENDENCY_INSTALL_DIR}/bin/macdeployqt ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app + COMMAND ${MACDEPLOYQT_APP} ${eth_qml_dir} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # This tool and next will inspect linked libraries in order to determine which dependencies are required From 5162715101adc9df8b3713039a9f33479e2eb9a0 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sun, 14 Dec 2014 00:10:52 +0100 Subject: [PATCH 03/10] ungly fix for compiling exp on mac --- exp/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/exp/main.cpp b/exp/main.cpp index 3c4a1b207..27707decb 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -20,6 +20,7 @@ * Ethereum client. */ #include +#include #include #include #include From 960f62b05a9a61300400dd566d5ad815f24e3101 Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sun, 14 Dec 2014 21:20:59 +0800 Subject: [PATCH 04/10] update to the correct file name --- alethzero/OurWebThreeStubServer.cpp | 2 +- alethzero/OurWebThreeStubServer.h | 2 +- libdevcore/CommonData.cpp | 2 +- libdevcore/CommonData.h | 2 +- libdevcore/RangeMask.h | 2 +- libdevcrypto/OverlayDB.cpp | 2 +- libdevcrypto/OverlayDB.h | 2 +- libdevcrypto/SHA3.h | 2 +- libethereum/CommonNet.cpp | 2 +- libethereum/CommonNet.h | 2 +- libevmcore/Assembly.h | 2 +- libp2p/HostCapability.h | 2 +- libwhisper/Interface.h | 2 +- mix/CodeEditorExtensionManager.cpp | 2 +- mix/CodeEditorExtensionManager.h | 2 +- mix/ConstantCompilationCtrl.cpp | 2 +- mix/ConstantCompilationCtrl.h | 2 +- mix/ConstantCompilationModel.cpp | 2 +- mix/ConstantCompilationModel.h | 2 +- mix/Extension.cpp | 2 +- mix/Extension.h | 2 +- mix/MixApplication.cpp | 2 +- mix/MixApplication.h | 2 +- test/genesis.cpp | 2 +- test/hexPrefix.cpp | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index fec0f9e8d..0c6f42b5a 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file OurWebThreeStubServer.h +/** @file OurWebThreeStubServer.cpp * @author Gav Wood * @date 2014 */ diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index ef13964b9..fb026d07e 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file OurWebThreeStubServer.cpp +/** @file OurWebThreeStubServer.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 215f9c4b3..fc3910cfe 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.cpp +/** @file CommonData.cpp * @author Gav Wood * @date 2014 */ diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 5f14f38f8..87d2f5e28 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.h +/** @file CommonData.h * @author Gav Wood * @date 2014 * diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index ac58ec8b1..19262515c 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file EthereumHost.h +/** @file RangeMask.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index 8ccae6606..9e110bb84 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file TrieDB.cpp +/** @file OverlayDB.cpp * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/OverlayDB.h b/libdevcrypto/OverlayDB.h index 777d1e7df..e9bd53343 100644 --- a/libdevcrypto/OverlayDB.h +++ b/libdevcrypto/OverlayDB.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file MemoryDB.h +/** @file OverlayDB.h * @author Gav Wood * @date 2014 */ diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index f27e378ba..66b8efe11 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file FixedHash.h +/** @file SHA3.h * @author Gav Wood * @date 2014 * diff --git a/libethereum/CommonNet.cpp b/libethereum/CommonNet.cpp index eb92f0b18..5a9d3d0c9 100644 --- a/libethereum/CommonNet.cpp +++ b/libethereum/CommonNet.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file PeerNetwork.cpp +/** @file CommonNet.cpp * @author Gav Wood * @date 2014 */ diff --git a/libethereum/CommonNet.h b/libethereum/CommonNet.h index 4192c861e..2ee260650 100644 --- a/libethereum/CommonNet.h +++ b/libethereum/CommonNet.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file PeerNetwork.h +/** @file CommonNet.h * @author Gav Wood * @date 2014 * diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index b144dd8d9..5523710d4 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeFragment.h +/** @file Assembly.h * @author Gav Wood * @date 2014 */ diff --git a/libp2p/HostCapability.h b/libp2p/HostCapability.h index da454860a..9666ef65a 100644 --- a/libp2p/HostCapability.h +++ b/libp2p/HostCapability.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Common.h +/** @file HostCapability.h * @author Gav Wood * @date 2014 * diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 1af93f591..0b7b52cf7 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file WhisperHost.h +/** @file Interface.h * @author Gav Wood * @date 2014 */ diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index c778d466f..9d0e8508d 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeEditorExtensionMan.cpp +/** @file CodeEditorExtensionManager.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/CodeEditorExtensionManager.h b/mix/CodeEditorExtensionManager.h index 2b8402bf2..522429511 100644 --- a/mix/CodeEditorExtensionManager.h +++ b/mix/CodeEditorExtensionManager.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file CodeEditorExtensionMan.h +/** @file CodeEditorExtensionManager.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationCtrl.cpp b/mix/ConstantCompilationCtrl.cpp index 06b9c0284..12eca8a40 100644 --- a/mix/ConstantCompilationCtrl.cpp +++ b/mix/ConstantCompilationCtrl.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ConstantCompilation.cpp +/** @file ConstantCompilationCtrl.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationCtrl.h b/mix/ConstantCompilationCtrl.h index e4661c800..8e32b7589 100644 --- a/mix/ConstantCompilationCtrl.h +++ b/mix/ConstantCompilationCtrl.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ConstantCompilation.h +/** @file ConstantCompilationCtrl.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationModel.cpp b/mix/ConstantCompilationModel.cpp index ea12a267c..722305763 100644 --- a/mix/ConstantCompilationModel.cpp +++ b/mix/ConstantCompilationModel.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/ConstantCompilationModel.h b/mix/ConstantCompilationModel.h index 4a17853f6..9b8855a3e 100644 --- a/mix/ConstantCompilationModel.h +++ b/mix/ConstantCompilationModel.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file ApplicationCtx.h +/** @file ConstantCompilationModel.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 5aeb0cc17..cb1394194 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Feature.cpp +/** @file Extension.cpp * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/Extension.h b/mix/Extension.h index f8fef0aa6..84fe8e2dc 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Feature.h +/** @file Extension.h * @author Yann yann@ethdev.com * @date 2014 * Ethereum IDE client. diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index e67ca1b12..d374188b9 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file MixApplication.cpp * @author Yann yann@ethdev.com * @date 2014 */ diff --git a/mix/MixApplication.h b/mix/MixApplication.h index fdc506268..b0ea0f216 100644 --- a/mix/MixApplication.h +++ b/mix/MixApplication.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file MixApplication.h * @author Yann yann@ethdev.com * @date 2014 * This class will be use instead of QApplication to launch the application. the method 'notify' allows to catch all exceptions. diff --git a/test/genesis.cpp b/test/genesis.cpp index 1b354dab8..8cdb84024 100644 --- a/test/genesis.cpp +++ b/test/genesis.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file trie.cpp +/** @file genesis.cpp * @author Gav Wood * @date 2014 * Trie test functions. diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index 1f02bac91..551983db3 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file main.cpp +/** @file hexPrefix.cpp * @author Gav Wood * @date 2014 * Main test functions. From 5652bd37790be8b0ce9ccb70f0220a9dfdbf8e6f Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sun, 14 Dec 2014 21:21:35 +0800 Subject: [PATCH 05/10] typo fix --- libp2p/Session.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/Session.h b/libp2p/Session.h index e8de1c398..cd2dbf5a7 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -110,7 +110,7 @@ private: std::array m_data; ///< Data buffer for the write queue. bytes m_incoming; ///< The incoming read queue of bytes. - PeerInfo m_info; ///< Dyanamic information about this peer. + PeerInfo m_info; ///< Dynamic information about this peer. unsigned m_protocolVersion = 0; ///< The protocol version of the peer. std::shared_ptr m_node; ///< The Node object. Might be null if we constructed using a bare address/port. From 092528d87aba350c01f58b4c24cc4405d2da2f57 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 18:48:43 +0100 Subject: [PATCH 06/10] Minor fix for finalize. --- libethereum/Executive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 438505f1a..ed3077628 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -220,7 +220,8 @@ bool Executive::go(OnOpFunc const& _onOp) void Executive::finalize(OnOpFunc const&) { // SSTORE refunds. - m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); + if (m_ext) + m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; m_s.addBalance(m_sender, m_endGas * m_t.gasPrice()); From b6aa6efb4623674b2898607827fe4060e1e2a56f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 18:49:44 +0100 Subject: [PATCH 07/10] Another fix for finalize. --- libethereum/Executive.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index ed3077628..f05591ba2 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -236,5 +236,6 @@ void Executive::finalize(OnOpFunc const&) m_s.m_cache[a].kill(); // Logs - m_logs = m_ext->sub.logs; + if (m_ext) + m_logs = m_ext->sub.logs; } From 302c16ec4475c73c77f4ebd799182e4beaa8cc3a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 14 Dec 2014 21:10:17 +0100 Subject: [PATCH 08/10] Documentation and reduction. --- libethereum/Executive.cpp | 37 ++++++++++--------- libethereum/Executive.h | 75 +++++++++++++++++++++++++++------------ libethereum/ExtVM.cpp | 4 +-- 3 files changed, 72 insertions(+), 44 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f05591ba2..d16cf794c 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -40,15 +40,19 @@ u256 Executive::gasUsed() const return m_t.gas() - m_endGas; } +void Executive::accrueSubState(SubState& _parentContext) +{ + if (m_ext) + _parentContext += m_ext->sub; +} + bool Executive::setup(bytesConstRef _rlp) { // Entry point for a user-executed transaction. m_t = Transaction(_rlp); - m_sender = m_t.sender(); - // Avoid invalid transactions. - auto nonceReq = m_s.transactionsFrom(m_sender); + auto nonceReq = m_s.transactionsFrom(m_t.sender()); if (m_t.nonce() != nonceReq) { clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce(); @@ -67,10 +71,10 @@ bool Executive::setup(bytesConstRef _rlp) u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice(); // Avoid unaffordable transactions. - if (m_s.balance(m_sender) < cost) + if (m_s.balance(m_t.sender()) < cost) { - clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender))); + clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_t.sender()); + BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_t.sender()))); } u256 startGasUsed = m_s.gasUsed(); @@ -81,16 +85,16 @@ bool Executive::setup(bytesConstRef _rlp) } // Increment associated nonce for sender. - m_s.noteSending(m_sender); + m_s.noteSending(m_t.sender()); // Pay... clog(StateDetail) << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas() << "gas at" << formatBalance(m_t.gasPrice()) << ")"; - m_s.subBalance(m_sender, cost); + m_s.subBalance(m_t.sender(), cost); if (m_t.isCreation()) - return create(m_sender, m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_sender); + return create(m_t.sender(), m_t.value(), m_t.gasPrice(), m_t.gas() - (u256)gasCost, &m_t.data(), m_t.sender()); else - return call(m_t.receiveAddress(), m_t.receiveAddress(), m_sender, m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_sender); + return call(m_t.receiveAddress(), m_t.receiveAddress(), m_t.sender(), m_t.value(), m_t.gasPrice(), bytesConstRef(&m_t.data()), m_t.gas() - (u256)gasCost, m_t.sender()); } bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256 _gas, Address _originAddress) @@ -212,22 +216,17 @@ bool Executive::go(OnOpFunc const& _onOp) return true; } -/*u256 Executive::gas() const -{ - return m_vm ? m_vm->gas() : m_endGas; -}*/ - void Executive::finalize(OnOpFunc const&) { - // SSTORE refunds. + // SSTORE refunds... + // must be done before the miner gets the fees. if (m_ext) m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.refunds); // cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")"; - m_s.addBalance(m_sender, m_endGas * m_t.gasPrice()); + m_s.addBalance(m_t.sender(), m_endGas * m_t.gasPrice()); u256 feesEarned = (m_t.gas() - m_endGas) * m_t.gasPrice(); -// cnote << "Transferring" << formatBalance(gasSpent) << "to miner."; m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned); // Suicides... @@ -235,7 +234,7 @@ void Executive::finalize(OnOpFunc const&) for (auto a: m_ext->sub.suicides) m_s.m_cache[a].kill(); - // Logs + // Logs.. if (m_ext) m_logs = m_ext->sub.logs; } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index c5baada1d..729014bef 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -39,53 +39,82 @@ struct Manifest; struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; }; - +/** + * @brief Message-call/contract-creation executor; useful for executing transactions. + * + * Two ways of using this class - either as a transaction executive or a CALL/CREATE executive. + * In the first use, after construction, begin with setup() and end with finalize(). Call go() + * after setup() only if it returns false. + * In the second use, after construction, begin with call() or create() and end with + * accrueSubState(). Call go() after call()/create() only if it returns false. + */ class Executive { public: + /// Basic constructor. Executive(State& _s, unsigned _level): m_s(_s), m_depth(_level) {} + /// Basic destructor. ~Executive() = default; + Executive(Executive const&) = delete; void operator=(Executive) = delete; + /// Set up the executive for evaluating a transaction. You must call finalize() following this. + /// @returns true iff go() must be called (and thus a VM execution in required). bool setup(bytesConstRef _transaction); + /// Finalise a transaction previously set up with setup(). + /// @warning Only valid after setup(), and possibly go(). + void finalize(OnOpFunc const& _onOp = OnOpFunc()); + /// @returns the transaction from setup(). + /// @warning Only valid after setup(). + Transaction const& t() const { return m_t; } + /// @returns the log entries created by this operation. + /// @warning Only valid after finalise(). + LogEntries const& logs() const { return m_logs; } + /// @returns total gas used in the transaction/operation. + /// @warning Only valid after finalise(). + u256 gasUsed() const; + + /// Set up the executive for evaluating a bare CREATE (contract-creation) operation. + /// @returns false iff go() must be called (and thus a VM execution in required). bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress); + /// Set up the executive for evaluating a bare CALL (message call) operation. + /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress); + /// Finalise an operation through accruing the substate into the parent context. + void accrueSubState(SubState& _parentContext); + + /// Executes (or continues execution of) the VM. + /// @returns false iff go() must be called again to finish the transction. bool go(OnOpFunc const& _onOp = OnOpFunc()); - void finalize(OnOpFunc const& _onOp = OnOpFunc()); - u256 gasUsed() const; + /// Operation function for providing a simple trace of the VM execution. static OnOpFunc simpleTrace(); - Transaction const& t() const { return m_t; } - + /// @returns gas remaining after the transaction/operation. u256 endGas() const { return m_endGas; } - + /// @returns output data of the transaction/operation. bytesConstRef out() const { return m_out; } + /// @returns the new address for the created contract in the CREATE operation. h160 newAddress() const { return m_newAddress; } - LogEntries const& logs() const { return m_logs; } + /// @returns true iff the operation ended with a VM exception. bool excepted() const { return m_excepted; } - VMFace const& vm() const { return *m_vm; } - ExtVM const& ext() const { return *m_ext; } - State const& state() const { return m_s; } - private: - State& m_s; - std::shared_ptr m_ext; - std::unique_ptr m_vm; + State& m_s; ///< The state to which this operation/transaction is applied. + std::shared_ptr m_ext; ///< The VM externality object for the VM execution or null if no VM is required. + std::unique_ptr m_vm; ///< The VM object or null if no VM is required. bytes m_precompiledOut; ///< Used for the output when there is no VM for a contract (i.e. precompiled). - bytesConstRef m_out; ///< Holds the copyable output. - Address m_newAddress; + bytesConstRef m_out; ///< The copyable output. + Address m_newAddress; ///< The address of the created contract in the case of create() being called. - Transaction m_t; - bool m_isCreation; - bool m_excepted = false; - unsigned m_depth = 0; - Address m_sender; - u256 m_endGas; + unsigned m_depth = 0; ///< The context's call-depth. + bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called. + bool m_excepted = false; ///< True if the VM execution resulted in an exception. + u256 m_endGas; ///< The final amount of gas for the transaction. - LogEntries m_logs; + Transaction m_t; ///< The original transaction in the case that setup() was called. + LogEntries m_logs; ///< The log entries created by this transaction. Only valid }; } diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index fcd703b25..a005a030b 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -32,7 +32,7 @@ bool ExtVM::call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, if (!e.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, origin)) { e.go(_onOp); - sub += e.ext().sub; + e.accrueSubState(sub); } io_gas = e.endGas(); e.out().copyTo(_out); @@ -49,7 +49,7 @@ h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin)) { e.go(_onOp); - sub += e.ext().sub; + e.accrueSubState(sub); } io_gas = e.endGas(); return e.newAddress(); From 8eee0a2033d3539ffc1bf311a5021322d7bc4fe5 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 01:02:33 +0100 Subject: [PATCH 09/10] Correctly check for string prefix plus indentation change. --- libsolidity/ExpressionCompiler.cpp | 2 +- libsolidity/Types.cpp | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index add5f73be..f872e0581 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -291,7 +291,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::ADDRESS), true); m_context << eth::Instruction::BALANCE; } - else if (member == "send" || member.substr(0, 4) == "call") + else if (member == "send" || member.substr(0, min(member.size(), 4)) == "call") appendTypeConversion(*_memberAccess.getExpression().getType(), IntegerType(0, IntegerType::Modifier::ADDRESS), true); else diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index a0a809b9b..c2d488418 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -193,14 +193,18 @@ u256 IntegerType::literalValue(Literal const& _literal) const } const MemberList IntegerType::AddressMemberList = - MemberList({{"balance", make_shared(256)}, - {"callstring32", make_shared(TypePointers({make_shared(32)}), - TypePointers(), FunctionType::Location::BARE)}, - {"callstring32string32", make_shared(TypePointers({make_shared(32), - make_shared(32)}), - TypePointers(), FunctionType::Location::BARE)}, - {"send", make_shared(TypePointers({make_shared(256)}), - TypePointers(), FunctionType::Location::SEND)}}); + MemberList({{"balance", + make_shared(256)}, + {"callstring32", + make_shared(TypePointers({make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"callstring32string32", + make_shared(TypePointers({make_shared(32), + make_shared(32)}), + TypePointers(), FunctionType::Location::BARE)}, + {"send", + make_shared(TypePointers({make_shared(256)}), + TypePointers(), FunctionType::Location::SEND)}}); shared_ptr StaticStringType::smallestTypeForLiteral(string const& _literal) { From f42f24165bc9f2385d5d9779eb540fd86acee87b Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 15 Dec 2014 10:43:22 +0100 Subject: [PATCH 10/10] Bugfix: Avoid accessing temporary after its lifetime. --- eth/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 49eac8876..1520e86c4 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -441,9 +441,8 @@ int main(int argc, char** argv) #endif else if (cmd == "address") { - cout << "Current address:" << endl; - const char* addchr = toHex(us.address().asArray()).c_str(); - cout << addchr << endl; + cout << "Current address:" << endl + << toHex(us.address().asArray()) << endl; } else if (cmd == "secret") {