Browse Source

Merge remote-tracking branch 'upstream/develop' into NewStateTests

cl-refactor
CJentzsch 10 years ago
parent
commit
aa509e90bc
  1. 2
      alethzero/OurWebThreeStubServer.cpp
  2. 2
      alethzero/OurWebThreeStubServer.h
  3. 11
      cmake/EthDependencies.cmake
  4. 2
      cmake/EthExecutableHelper.cmake
  5. 5
      eth/main.cpp
  6. 1
      exp/main.cpp
  7. 2
      libdevcore/CommonData.cpp
  8. 2
      libdevcore/CommonData.h
  9. 2
      libdevcore/RangeMask.h
  10. 2
      libdevcrypto/OverlayDB.cpp
  11. 2
      libdevcrypto/OverlayDB.h
  12. 2
      libdevcrypto/SHA3.h
  13. 2
      libethereum/CommonNet.cpp
  14. 2
      libethereum/CommonNet.h
  15. 43
      libethereum/Executive.cpp
  16. 75
      libethereum/Executive.h
  17. 4
      libethereum/ExtVM.cpp
  18. 2
      libevmcore/Assembly.h
  19. 2
      libp2p/HostCapability.h
  20. 2
      libp2p/Session.h
  21. 122
      libsolidity/ExpressionCompiler.cpp
  22. 20
      libsolidity/ExpressionCompiler.h
  23. 17
      libsolidity/Types.cpp
  24. 3
      libsolidity/Types.h
  25. 2
      libwhisper/Interface.h
  26. 2
      mix/CodeEditorExtensionManager.cpp
  27. 2
      mix/CodeEditorExtensionManager.h
  28. 2
      mix/ConstantCompilationCtrl.cpp
  29. 2
      mix/ConstantCompilationCtrl.h
  30. 2
      mix/ConstantCompilationModel.cpp
  31. 2
      mix/ConstantCompilationModel.h
  32. 2
      mix/Extension.cpp
  33. 2
      mix/Extension.h
  34. 2
      mix/MixApplication.cpp
  35. 2
      mix/MixApplication.h
  36. 2
      test/genesis.cpp
  37. 2
      test/hexPrefix.cpp

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.h
/** @file OurWebThreeStubServer.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file OurWebThreeStubServer.cpp
/** @file OurWebThreeStubServer.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

11
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

2
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

5
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")
{

1
exp/main.cpp

@ -20,6 +20,7 @@
* Ethereum client.
*/
#include <functional>
#include <libethereum/AccountDiff.h>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file Common.cpp
/** @file CommonData.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file Common.h
/** @file CommonData.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file EthereumHost.h
/** @file RangeMask.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file TrieDB.cpp
/** @file OverlayDB.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file MemoryDB.h
/** @file OverlayDB.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file FixedHash.h
/** @file SHA3.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file PeerNetwork.cpp
/** @file CommonNet.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file PeerNetwork.h
/** @file CommonNet.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*

43
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,21 +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.
m_endGas += min((m_t.gas() - m_endGas) / 2, m_ext->sub.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...
@ -234,6 +234,7 @@ void Executive::finalize(OnOpFunc const&)
for (auto a: m_ext->sub.suicides)
m_s.m_cache[a].kill();
// Logs
m_logs = m_ext->sub.logs;
// Logs..
if (m_ext)
m_logs = m_ext->sub.logs;
}

75
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<ExtVM> m_ext;
std::unique_ptr<VMFace> m_vm;
State& m_s; ///< The state to which this operation/transaction is applied.
std::shared_ptr<ExtVM> m_ext; ///< The VM externality object for the VM execution or null if no VM is required.
std::unique_ptr<VMFace> 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
};
}

4
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();

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file CodeFragment.h
/** @file Assembly.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file Common.h
/** @file HostCapability.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*

2
libp2p/Session.h

@ -110,7 +110,7 @@ private:
std::array<byte, 65536> 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<Node> m_node; ///< The Node object. Might be null if we constructed using a bare address/port.

122
libsolidity/ExpressionCompiler.cpp

@ -194,7 +194,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else
{
FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType());
std::vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments();
vector<ASTPointer<Expression const>> 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, min<size_t>(member.size(), 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<ASTPointer<Expression const>> 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),

20
libsolidity/ExpressionCompiler.h

@ -20,6 +20,7 @@
* Solidity AST to EVM bytecode compiler for expressions.
*/
#include <functional>
#include <boost/noncopyable.hpp>
#include <libdevcore/Common.h>
#include <libsolidity/ASTVisitor.h>
@ -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<void()> obtainAddress;
/// Invoked to copy the ethe value to the stack (if not specified, value is 0).
std::function<void()> 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<ASTPointer<Expression const>> 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

17
libsolidity/Types.cpp

@ -193,9 +193,18 @@ u256 IntegerType::literalValue(Literal const& _literal) const
}
const MemberList IntegerType::AddressMemberList =
MemberList({{"balance", make_shared<IntegerType const>(256)},
{"send", make_shared<FunctionType const>(TypePointers({make_shared<IntegerType const>(256)}),
TypePointers(), FunctionType::Location::SEND)}});
MemberList({{"balance",
make_shared<IntegerType const>(256)},
{"callstring32",
make_shared<FunctionType const>(TypePointers({make_shared<StaticStringType const>(32)}),
TypePointers(), FunctionType::Location::BARE)},
{"callstring32string32",
make_shared<FunctionType const>(TypePointers({make_shared<StaticStringType const>(32),
make_shared<StaticStringType const>(32)}),
TypePointers(), FunctionType::Location::BARE)},
{"send",
make_shared<FunctionType const>(TypePointers({make_shared<IntegerType const>(256)}),
TypePointers(), FunctionType::Location::SEND)}});
shared_ptr<StaticStringType> StaticStringType::smallestTypeForLiteral(string const& _literal)
{
@ -424,6 +433,8 @@ unsigned FunctionType::getSizeOnStack() const
return 1;
case Location::EXTERNAL:
return 2;
case Location::BARE:
return 1;
default:
return 0;
}

3
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);

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file WhisperHost.h
/** @file Interface.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file CodeEditorExtensionMan.cpp
/** @file CodeEditorExtensionManager.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file CodeEditorExtensionMan.h
/** @file CodeEditorExtensionManager.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file ConstantCompilation.cpp
/** @file ConstantCompilationCtrl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file ConstantCompilation.h
/** @file ConstantCompilationCtrl.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file ApplicationCtx.h
/** @file ConstantCompilationModel.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file ApplicationCtx.h
/** @file ConstantCompilationModel.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file Feature.cpp
/** @file Extension.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file Feature.h
/** @file Extension.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
/** @file MixApplication.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/

2
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 <http://www.gnu.org/licenses/>.
*/
/** @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.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file trie.cpp
/** @file genesis.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Trie test functions.

2
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 <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
/** @file hexPrefix.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Main test functions.

Loading…
Cancel
Save