Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into

mix_srci

Conflicts:
	mix/qml/StatusPane.qml
cl-refactor
arkpar 10 years ago
parent
commit
1ddff7d9b7
  1. 1
      alethzero/CMakeLists.txt
  2. 13
      alethzero/MainWin.cpp
  3. 1
      alethzero/MainWin.h
  4. 3
      alethzero/Transact.cpp
  5. 2
      cmake/EthCompilerSettings.cmake
  6. 2
      cmake/FindJsonRpcCpp.cmake
  7. 20
      docker/Dockerfile
  8. 2
      eth/CMakeLists.txt
  9. 72
      eth/main.cpp
  10. 4
      libdevcore/CMakeLists.txt
  11. 194
      libdevcore/StructuredLogger.cpp
  12. 104
      libdevcore/StructuredLogger.h
  13. 46
      libdevcore/UndefMacros.h
  14. 2
      libdevcore/debugbreak.h
  15. 2
      libdevcrypto/CMakeLists.txt
  16. 2
      libethcore/CMakeLists.txt
  17. 14
      libethereum/BlockChain.cpp
  18. 2
      libethereum/BlockChain.h
  19. 7
      libethereum/CMakeLists.txt
  20. 36
      libethereum/Client.cpp
  21. 15
      libethereum/Client.h
  22. 1
      libethereum/EthereumHost.h
  23. 4
      libethereum/EthereumPeer.h
  24. 1
      libethereum/Miner.h
  25. 7
      libethereum/State.cpp
  26. 2
      libethereumx/CMakeLists.txt
  27. 2
      libevm/CMakeLists.txt
  28. 3
      libevm/ExtVMFace.h
  29. 2
      libevmcore/CMakeLists.txt
  30. 2
      libjsqrc/CMakeLists.txt
  31. 9
      libjsqrc/ethereumjs/README.md
  32. 2
      libjsqrc/ethereumjs/bower.json
  33. 114
      libjsqrc/ethereumjs/dist/ethereum.js
  34. 10
      libjsqrc/ethereumjs/dist/ethereum.js.map
  35. 2
      libjsqrc/ethereumjs/dist/ethereum.min.js
  36. 31
      libjsqrc/ethereumjs/lib/abi.js
  37. 11
      libjsqrc/ethereumjs/lib/contract.js
  38. 10
      libjsqrc/ethereumjs/lib/event.js
  39. 42
      libjsqrc/ethereumjs/lib/signature.js
  40. 2
      libjsqrc/ethereumjs/package.json
  41. 125
      libjsqrc/ethereumjs/test/abi.inputParser.js
  42. 2
      liblll/CMakeLists.txt
  43. 3
      libnatspec/CMakeLists.txt
  44. 7
      libp2p/CMakeLists.txt
  45. 3
      libp2p/Common.h
  46. 11
      libp2p/Host.cpp
  47. 8
      libp2p/Host.h
  48. 1
      libp2p/Network.cpp
  49. 2
      libp2p/NodeTable.h
  50. 6
      libp2p/Session.cpp
  51. 1
      libp2p/Session.h
  52. 1
      libp2p/UDP.h
  53. 2
      libserpent/CMakeLists.txt
  54. 2
      libsolidity/CMakeLists.txt
  55. 67
      libsolidity/Compiler.cpp
  56. 17
      libsolidity/ExpressionCompiler.cpp
  57. 1
      libsolidity/Token.h
  58. 13
      libsolidity/Types.cpp
  59. 3
      libsolidity/Types.h
  60. 3
      libweb3jsonrpc/CMakeLists.txt
  61. 3
      libweb3jsonrpc/WebThreeStubServer.cpp
  62. 4
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  63. 3
      libwebthree/CMakeLists.txt
  64. 14
      libwebthree/WebThree.cpp
  65. 14
      libwebthree/WebThree.h
  66. 3
      libwhisper/CMakeLists.txt
  67. 1
      libwhisper/Common.h
  68. 1
      libwhisper/Interface.h
  69. 1
      libwhisper/Message.h
  70. 4
      libwhisper/WhisperHost.cpp
  71. 1
      libwhisper/WhisperHost.h
  72. 1
      libwhisper/WhisperPeer.h
  73. 1
      mix/CMakeLists.txt
  74. 41
      mix/ClientModel.cpp
  75. 11
      mix/ClientModel.h
  76. 3
      mix/DebuggingStateWrapper.h
  77. 3
      mix/Extension.cpp
  78. 22
      mix/MixClient.cpp
  79. 6
      mix/MixClient.h
  80. 1
      mix/QContractDefinition.cpp
  81. 4
      mix/qml/Ether.qml
  82. 151
      mix/qml/StateDialog.qml
  83. 59
      mix/qml/StateListModel.qml
  84. 2
      mix/qml/StatusPane.qml
  85. 33
      mix/qml/TransactionDialog.qml
  86. 6
      mix/qml/TransactionLog.qml
  87. 1
      neth/CMakeLists.txt
  88. 2
      neth/main.cpp
  89. 14
      secp256k1/CMakeLists.txt
  90. 19
      test/SolidityEndToEndTest.cpp
  91. 4
      test/TestHelper.cpp
  92. 4
      test/TestHelper.h
  93. 144
      test/block.cpp
  94. 2
      test/createRandomTest.cpp
  95. 1
      test/fork.cpp
  96. 4
      test/genesis.cpp
  97. 4
      test/hexPrefix.cpp
  98. 1
      test/net.cpp
  99. 4
      test/rlp.cpp
  100. 3
      test/state.cpp

1
alethzero/CMakeLists.txt

@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
qt5_wrap_ui(ui_Main.h Main.ui) qt5_wrap_ui(ui_Main.h Main.ui)
qt5_wrap_ui(ui_Debugger.h Debugger.ui) qt5_wrap_ui(ui_Debugger.h Debugger.ui)

13
alethzero/MainWin.cpp

@ -20,6 +20,10 @@
*/ */
#include <fstream> #include <fstream>
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QtWidgets/QFileDialog> #include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox> #include <QtWidgets/QMessageBox>
@ -1382,11 +1386,16 @@ void Main::on_blocks_currentItemChanged()
s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>"; s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>";
else else
s << "<br/>Pre: <i>Nothing is before Phil</i>"; s << "<br/>Pre: <i>Nothing is before Phil</i>";
BlockReceipts receipts = ethereum()->blockChain().receipts(h);
unsigned ii = 0;
for (auto const& i: block[1]) for (auto const& i: block[1])
s << "<br/>" << sha3(i.data()).abridged();// << ": <b>" << i[1].toHash<h256>() << "</b> [<b>" << i[2].toInt<u256>() << "</b> used]"; {
s << "<br/>" << sha3(i.data()).abridged() << ": <b>" << receipts.receipts[ii].stateRoot() << "</b> [<b>" << receipts.receipts[ii].gasUsed() << "</b> used]";
++ii;
}
s << "<br/>Post: <b>" << info.stateRoot << "</b>"; s << "<br/>Post: <b>" << info.stateRoot << "</b>";
s << "<br/>Dump: " Span(Mono) << toHex(block[0].data()) << "</span>"; s << "<br/>Dump: " Span(Mono) << toHex(block[0].data()) << "</span>";
s << "<div>Receipts-Hex: " Span(Mono) << toHex(ethereum()->blockChain().receipts(h).rlp()) << "</span></div>"; s << "<div>Receipts-Hex: " Span(Mono) << toHex(receipts.rlp()) << "</span></div>";
} }
else else
{ {

1
alethzero/MainWin.h

@ -26,6 +26,7 @@
#endif #endif
#include <map> #include <map>
#include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkAccessManager>
#include <QtCore/QAbstractListModel> #include <QtCore/QAbstractListModel>
#include <QtCore/QMutex> #include <QtCore/QMutex>

3
alethzero/Transact.cpp

@ -19,6 +19,9 @@
* @date 2015 * @date 2015
*/ */
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include "Transact.h" #include "Transact.h"
#include <fstream> #include <fstream>

2
cmake/EthCompilerSettings.cmake

@ -3,7 +3,7 @@
# C++11 check and activation # C++11 check and activation
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -DSHAREDLIB -fPIC") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -DSHAREDLIB -fPIC ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")

2
cmake/FindJsonRpcCpp.cmake

@ -14,7 +14,7 @@
# only look in default directories # only look in default directories
find_path( find_path(
JSON_RPC_CPP_INCLUDE_DIR JSON_RPC_CPP_INCLUDE_DIR
NAMES jsonrpccpp/server.h NAMES jsonrpccpp/server.h jsonrpc/server.h
PATH_SUFFIXES jsonrpc PATH_SUFFIXES jsonrpc
DOC "json-rpc-cpp include dir" DOC "json-rpc-cpp include dir"
) )

20
docker/Dockerfile

@ -8,23 +8,29 @@ RUN apt-get upgrade -y
RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget
RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev RUN apt-get install -qy libjsoncpp-dev libargtable2-dev
RUN apt-get install -qy libncurses5-dev libcurl4-openssl-dev wget
# NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 ) RUN apt-get install -qy libjsoncpp-dev libargtable2-dev libmicrohttpd-dev
RUN apt-get install -qy libncurses5-dev
# Qt-based GUI
# RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev
# Ethereum PPA # Ethereum PPA
RUN apt-get install -qy software-properties-common RUN apt-get install -qy software-properties-common
RUN add-apt-repository ppa:ethereum/ethereum RUN add-apt-repository ppa:ethereum/ethereum
RUN add-apt-repository ppa:ethereum/ethereum-dev
RUN apt-get update RUN apt-get update
RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev
# LLVM-3.5
RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main\ndeb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main" > /etc/apt/sources.list.d/llvm-trusty.list
RUN apt-get update
RUN apt-get install -qy llvm-3.5 libedit-dev
# Fix llvm-3.5 cmake paths
RUN mkdir -p /usr/lib/llvm-3.5/share/llvm && ln -s /usr/share/llvm-3.5/cmake /usr/lib/llvm-3.5/share/llvm/cmake
# Build Ethereum (HEADLESS) # Build Ethereum (HEADLESS)
RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum
RUN mkdir -p cpp-ethereum/build RUN mkdir -p cpp-ethereum/build
RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DHEADLESS=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install RUN cd cpp-ethereum/build && cmake .. -DHEADLESS=1 -DLLVM_DIR=/usr/share/llvm-3.5/cmake -DEVMJIT=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install
RUN ldconfig RUN ldconfig
ENTRYPOINT ["/usr/local/bin/eth"] ENTRYPOINT ["/usr/local/bin/eth"]

2
eth/CMakeLists.txt

@ -28,7 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
if (WIN32) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
endif() endif()

72
eth/main.cpp

@ -25,10 +25,13 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <signal.h> #include <signal.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp> #include <boost/algorithm/string/trim_all.hpp>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcore/StructuredLogger.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include <libethereum/All.h> #include <libethereum/All.h>
@ -97,38 +100,40 @@ void interactiveHelp()
void help() void help()
{ {
cout cout
<< "Usage eth [OPTIONS] <remote-host>" << endl << "Usage eth [OPTIONS] <remote-host>" << endl
<< "Options:" << endl << "Options:" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl << " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
<< " -c,--client-name <name> Add a name to your client's version string (default: blank)." << endl << " -c,--client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -d,--db-path <path> Load database from path (default: ~/.ethereum " << endl << " -d,--db-path <path> Load database from path (default: ~/.ethereum " << endl
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl << " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
<< " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
<< " -h,--help Show this help message and exit." << endl << " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
#if ETH_JSONRPC #if ETH_JSONRPC
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl
#endif #endif
<< " -l,--listen <port> Listen on the given port for incoming connected (default: 30303)." << endl << " -l,--listen <port> Listen on the given port for incoming connected (default: 30303)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (Default: off)" << endl << " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (Default: off)" << endl
<< " -n,--upnp <on/off> Use upnp for NAT (default: on)." << endl << " -n,--upnp <on/off> Use upnp for NAT (default: on)." << endl
<< " -L,--local-networking Use peers whose addresses are local." << endl << " -L,--local-networking Use peers whose addresses are local." << endl
<< " -o,--mode <full/peer> Start a full node or a peer node (Default: full)." << endl << " -o,--mode <full/peer> Start a full node or a peer node (Default: full)." << endl
<< " -p,--port <port> Connect to remote port (default: 30303)." << endl << " -p,--port <port> Connect to remote port (default: 30303)." << endl
<< " -r,--remote <host> Connect to remote host (default: none)." << endl << " -r,--remote <host> Connect to remote host (default: none)." << endl
<< " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl << " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl
<< " -t,--miners <number> Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl << " --structured-logging Enables structured logging." << endl
<< " -u,--public-ip <ip> Force public ip to given (default; auto)." << endl << " --structured-logging-format <time-format> Give time format string for structured logging output." << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl << " -t,--miners <number> Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (Default: 5)." << endl << " -u,--public-ip <ip> Force public ip to given (default; auto)." << endl
<< " -V,--version Show the version and exit." << endl << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (Default: 5)." << endl
<< " -V,--version Show the version and exit." << endl
#if ETH_EVMJIT #if ETH_EVMJIT
<< " --jit Use EVM JIT (default: off)." << endl << " --jit Use EVM JIT (default: off)." << endl
#endif #endif
; ;
exit(0); exit(0);
} }
string credits(bool _interactive = false) string credits(bool _interactive = false)
@ -207,6 +212,8 @@ int main(int argc, char** argv)
bool useLocal = false; bool useLocal = false;
bool forceMining = false; bool forceMining = false;
bool jit = false; bool jit = false;
bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
string clientName; string clientName;
// Init defaults // Init defaults
@ -279,6 +286,10 @@ int main(int argc, char** argv)
} }
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i]))); us = KeyPair(h256(fromHex(argv[++i])));
else if (arg == "--structured-logging-format" && i + 1 < argc)
structuredLoggingFormat = string(argv[++i]);
else if (arg == "--structured-logging")
structuredLogging = true;
else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc)
dbPath = argv[++i]; dbPath = argv[++i];
else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) else if ((arg == "-m" || arg == "--mining") && i + 1 < argc)
@ -350,11 +361,13 @@ int main(int argc, char** argv)
cout << credits(); cout << credits();
StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal);
auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp");
std::string clientImplString = "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
dev::WebThreeDirect web3( dev::WebThreeDirect web3(
"Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : ""), clientImplString,
dbPath, dbPath,
false, false,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(), mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
@ -364,7 +377,7 @@ int main(int argc, char** argv)
); );
web3.setIdealPeerCount(peers); web3.setIdealPeerCount(peers);
eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr;
StructuredLogger::starting(clientImplString, dev::Version);
if (c) if (c)
{ {
c->setForceMining(forceMining); c->setForceMining(forceMining);
@ -898,6 +911,7 @@ int main(int argc, char** argv)
while (!g_exit) while (!g_exit)
this_thread::sleep_for(chrono::milliseconds(1000)); this_thread::sleep_for(chrono::milliseconds(1000));
StructuredLogger::stopping(clientImplString, dev::Version);
auto netData = web3.saveNetwork(); auto netData = web3.saveNetwork();
if (!netData.empty()) if (!netData.empty())
writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData);

4
libdevcore/CMakeLists.txt

@ -12,6 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
@ -27,6 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
# transitive dependencies for windows executables # transitive dependencies for windows executables
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
@ -42,6 +44,6 @@ elseif (UNIX)
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

194
libdevcore/StructuredLogger.cpp

@ -0,0 +1,194 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 StructuredLogger.h
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*
* A simple helper class for the structured logging
*/
#include "StructuredLogger.h"
#include <ctime>
#include <json/json.h>
#include "Guards.h"
using namespace std;
namespace dev
{
string StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts)
{
// not using C++11 std::put_time due to gcc bug
// http://stackoverflow.com/questions/14136833/stdput-time-implementation-status-in-gcc
char buffer[64];
time_t time = chrono::system_clock::to_time_t(_ts);
tm* ptm = localtime(&time);
if (strftime(buffer, sizeof(buffer), get().m_timeFormat.c_str(), ptm))
return string(buffer);
return "";
}
void StructuredLogger::outputJson(Json::Value const& _value, std::string const& _name) const
{
Json::Value event;
static Mutex s_lock;
Guard l(s_lock);
event[_name] = _value;
cout << event << endl << flush;
}
void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersion)
{
if (get().m_enabled)
{
Json::Value event;
event["client_impl"] = _clientImpl;
event["eth_version"] = std::string(_ethVersion);
event["ts"] = timePointToString(std::chrono::system_clock::now());
get().outputJson(event, "starting");
}
}
void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersion)
{
if (get().m_enabled)
{
Json::Value event;
event["client_impl"] = _clientImpl;
event["eth_version"] = std::string(_ethVersion);
event["ts"] = timePointToString(std::chrono::system_clock::now());
get().outputJson(event, "stopping");
}
}
void StructuredLogger::p2pConnected(
string const& _id,
bi::tcp::endpoint const& _addr,
chrono::system_clock::time_point const& _ts,
string const& _remoteVersion,
unsigned int _numConnections)
{
if (get().m_enabled)
{
std::stringstream addrStream;
addrStream << _addr;
Json::Value event;
event["remote_version_string"] = _remoteVersion;
event["remote_addr"] = addrStream.str();
event["remote_id"] = _id;
event["num_connections"] = Json::Value(_numConnections);
event["ts"] = timePointToString(_ts);
get().outputJson(event, "p2p.connected");
}
}
void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections)
{
if (get().m_enabled)
{
std::stringstream addrStream;
addrStream << _addr;
Json::Value event;
event["remote_addr"] = addrStream.str();
event["remote_id"] = _id;
event["num_connections"] = Json::Value(_numConnections);
event["ts"] = timePointToString(chrono::system_clock::now());
get().outputJson(event, "p2p.disconnected");
}
}
void StructuredLogger::minedNewBlock(
string const& _hash,
string const& _blockNumber,
string const& _chainHeadHash,
string const& _prevHash)
{
if (get().m_enabled)
{
Json::Value event;
event["block_hash"] = _hash;
event["block_number"] = _blockNumber;
event["chain_head_hash"] = _chainHeadHash;
event["ts"] = timePointToString(std::chrono::system_clock::now());
event["block_prev_hash"] = _prevHash;
get().outputJson(event, "eth.miner.new_block");
}
}
void StructuredLogger::chainReceivedNewBlock(
string const& _hash,
string const& _blockNumber,
string const& _chainHeadHash,
string const& _remoteID,
string const& _prevHash)
{
if (get().m_enabled)
{
Json::Value event;
event["block_hash"] = _hash;
event["block_number"] = _blockNumber;
event["chain_head_hash"] = _chainHeadHash;
event["remote_id"] = _remoteID;
event["ts"] = timePointToString(chrono::system_clock::now());
event["block_prev_hash"] = _prevHash;
get().outputJson(event, "eth.chain.received.new_block");
}
}
void StructuredLogger::chainNewHead(
string const& _hash,
string const& _blockNumber,
string const& _chainHeadHash,
string const& _prevHash)
{
if (get().m_enabled)
{
Json::Value event;
event["block_hash"] = _hash;
event["block_number"] = _blockNumber;
event["chain_head_hash"] = _chainHeadHash;
event["ts"] = timePointToString(chrono::system_clock::now());
event["block_prev_hash"] = _prevHash;
get().outputJson(event, "eth.miner.new_block");
}
}
void StructuredLogger::transactionReceived(string const& _hash, string const& _remoteId)
{
if (get().m_enabled)
{
Json::Value event;
event["tx_hash"] = _hash;
event["remote_id"] = _remoteId;
event["ts"] = timePointToString(chrono::system_clock::now());
get().outputJson(event, "eth.tx.received");
}
}
}

104
libdevcore/StructuredLogger.h

@ -0,0 +1,104 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 StructuredLogger.h
* @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*
* A simple helper class for the structured logging
* The spec for the implemented log events is here:
* https://github.com/ethereum/system-testing/wiki/Log-Events
*/
#pragma once
#include <string>
#include <chrono>
#include <libp2p/Network.h>
namespace Json { class Value; }
namespace dev
{
// TODO: Make the output stream configurable. stdout, stderr, file e.t.c.
class StructuredLogger
{
public:
/**
* Initializes the structured logger object
* @param _enabled Whether logging is on or off
* @param _timeFormat A time format string as described here:
* http://en.cppreference.com/w/cpp/chrono/c/strftime
* with which to display timestamps
*/
void initialize(bool _enabled, std::string const& _timeFormat)
{
m_enabled = _enabled;
m_timeFormat = _timeFormat;
}
static StructuredLogger& get()
{
static StructuredLogger instance;
return instance;
}
static void starting(std::string const& _clientImpl, const char* _ethVersion);
static void stopping(std::string const& _clientImpl, const char* _ethVersion);
static void p2pConnected(
std::string const& _id,
bi::tcp::endpoint const& _addr,
std::chrono::system_clock::time_point const& _ts,
std::string const& _remoteVersion,
unsigned int _numConnections
);
static void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections);
static void minedNewBlock(
std::string const& _hash,
std::string const& _blockNumber,
std::string const& _chainHeadHash,
std::string const& _prevHash
);
static void chainReceivedNewBlock(
std::string const& _hash,
std::string const& _blockNumber,
std::string const& _chainHeadHash,
std::string const& _remoteID,
std::string const& _prevHash
);
static void chainNewHead(
std::string const& _hash,
std::string const& _blockNumber,
std::string const& _chainHeadHash,
std::string const& _prevHash
);
static void transactionReceived(std::string const& _hash, std::string const& _remoteId);
private:
// Singleton class. Private default ctor and no copying
StructuredLogger() = default;
StructuredLogger(StructuredLogger const&) = delete;
void operator=(StructuredLogger const&) = delete;
/// @returns a string representation of a timepoint
static std::string timePointToString(std::chrono::system_clock::time_point const& _ts);
void outputJson(Json::Value const& _value, std::string const& _name) const;
bool m_enabled = false;
std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S";
};
}

46
libdevcore/UndefMacros.h

@ -0,0 +1,46 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 UndefMacros.h
* @author Lefteris <lefteris@ethdev.com>
* @date 2015
*
* This header should be used to #undef some really evil macros defined by
* windows.h which result in conflict with our libsolidity/Token.h
*/
#pragma once
#if defined(_MSC_VER) || defined(__MINGW32__)
#undef DELETE
#undef IN
#undef VOID
#undef THIS
#undef CONST
// Conflicting define on MinGW in windows.h
// windows.h(19): #define interface struct
#ifdef interface
#undef interface
#endif
#elif defined(DELETE) || defined(IN) || defined(VOID) || defined(THIS) || defined(CONST) || defined(interface)
#error "The preceding macros in this header file are reserved for V8's "\
"TOKEN_LIST. Please add a platform specific define above to undefine "\
"overlapping macros."
#endif

2
libdevcore/debugbreak.h

@ -27,7 +27,7 @@
#ifndef DEBUG_BREAK_H #ifndef DEBUG_BREAK_H
#define DEBUG_BREAK_H #define DEBUG_BREAK_H
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(__MINGW32__)
#define debug_break __debugbreak #define debug_break __debugbreak

2
libdevcrypto/CMakeLists.txt

@ -28,6 +28,6 @@ target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
libethcore/CMakeLists.txt

@ -25,6 +25,6 @@ endif()
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

14
libethereum/BlockChain.cpp

@ -25,6 +25,7 @@
#include <test/JsonSpiritHeaders.h> #include <test/JsonSpiritHeaders.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/StructuredLogger.h>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
@ -317,6 +318,13 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
} }
#endif #endif
StructuredLogger::chainReceivedNewBlock(
bi.headerHash(WithoutNonce).abridged(),
bi.nonce.abridged(),
currentHash().abridged(),
"", // TODO: remote id ??
bi.parentHash.abridged()
);
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
h256s ret; h256s ret;
@ -331,6 +339,12 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
} }
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret);
StructuredLogger::chainNewHead(
bi.headerHash(WithoutNonce).abridged(),
bi.nonce.abridged(),
currentHash().abridged(),
bi.parentHash.abridged()
);
} }
else else
{ {

2
libethereum/BlockChain.h

@ -96,7 +96,7 @@ public:
BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); } BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); }
BlockInfo info() const { return BlockInfo(block()); } BlockInfo info() const { return BlockInfo(block()); }
/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. /// Get the familiar details concerning a block (or the most recent mined if none given). Thread-safe.
BlockDetails details(h256 _hash) const { return queryExtras<BlockDetails, 0>(_hash, m_details, x_details, NullBlockDetails); } BlockDetails details(h256 _hash) const { return queryExtras<BlockDetails, 0>(_hash, m_details, x_details, NullBlockDetails); }
BlockDetails details() const { return details(currentHash()); } BlockDetails details() const { return details(currentHash()); }

7
libethereum/CMakeLists.txt

@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE ethereum) set(EXECUTABLE ethereum)
@ -35,6 +36,10 @@ target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) if (CMAKE_COMPILER_IS_MINGW)
target_link_libraries(${EXECUTABLE} ssp shlwapi)
endif()
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

36
libethereum/Client.cpp

@ -25,6 +25,7 @@
#include <thread> #include <thread>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/StructuredLogger.h>
#include <libp2p/Host.h> #include <libp2p/Host.h>
#include "Defaults.h" #include "Defaults.h"
#include "Executive.h" #include "Executive.h"
@ -59,7 +60,7 @@ void VersionChecker::setOk()
} }
} }
Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId, int miners): Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId, int _miners):
Worker("eth"), Worker("eth"),
m_vc(_dbPath), m_vc(_dbPath),
m_bc(_dbPath, !m_vc.ok() || _forceClean), m_bc(_dbPath, !m_vc.ok() || _forceClean),
@ -69,8 +70,8 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean,
{ {
m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId));
if (miners > -1) if (_miners > -1)
setMiningThreads(miners); setMiningThreads(_miners);
else else
setMiningThreads(); setMiningThreads();
if (_dbPath.size()) if (_dbPath.size())
@ -291,7 +292,7 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId)
return ret; return ret;
} }
void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed) void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3)
{ {
Guard l(m_filterLock); Guard l(m_filterLock);
for (pair<h256 const, InstalledFilter>& i: m_filters) for (pair<h256 const, InstalledFilter>& i: m_filters)
@ -303,7 +304,7 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& i
{ {
// filter catches them // filter catches them
for (LogEntry const& l: m) for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1)); i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _sha3));
io_changed.insert(i.first); io_changed.insert(i.first);
} }
} }
@ -319,14 +320,16 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
for (pair<h256 const, InstalledFilter>& i: m_filters) for (pair<h256 const, InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom))
// acceptable number & looks like block may contain a matching log entry. // acceptable number & looks like block may contain a matching log entry.
for (TransactionReceipt const& tr: br.receipts) for (size_t j = 0; j < br.receipts.size(); j++)
{ {
auto tr = br.receipts[j];
auto m = i.second.filter.matches(tr); auto m = i.second.filter.matches(tr);
if (m.size()) if (m.size())
{ {
auto sha3 = transaction(d.hash, j).sha3();
// filter catches them // filter catches them
for (LogEntry const& l: m) for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number)); i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, sha3));
io_changed.insert(i.first); io_changed.insert(i.first);
} }
} }
@ -415,6 +418,7 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _
} }
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged());
cnote << "New transaction " << t; cnote << "New transaction " << t;
m_tq.attemptImport(t.rlp()); m_tq.attemptImport(t.rlp());
} }
@ -582,8 +586,9 @@ void Client::doWork()
TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq); TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq);
if (newPendingReceipts.size()) if (newPendingReceipts.size())
{ {
for (auto i: newPendingReceipts) for (size_t i = 0; i < newPendingReceipts.size(); i++)
appendFromNewPending(i, changeds); appendFromNewPending(newPendingReceipts[i], changeds, m_postMine.pending()[i].sha3());
changeds.insert(PendingChangedFilter); changeds.insert(PendingChangedFilter);
if (isMining()) if (isMining())
@ -756,6 +761,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const
{ {
// Might have a transaction that contains a matching log. // Might have a transaction that contains a matching log.
TransactionReceipt const& tr = m_postMine.receipt(i); TransactionReceipt const& tr = m_postMine.receipt(i);
auto sha3 = m_postMine.pending()[i].sha3();
LogEntries le = _f.matches(tr); LogEntries le = _f.matches(tr);
if (le.size()) if (le.size())
{ {
@ -763,7 +769,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const
if (s) if (s)
s--; s--;
else else
ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin)); ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin, sha3));
} }
} }
begin = m_bc.number(); begin = m_bc.number();
@ -782,11 +788,15 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const
int total = 0; int total = 0;
#endif #endif
// check block bloom // check block bloom
if (_f.matches(m_bc.info(h).logBloom)) auto info = m_bc.info(h);
for (TransactionReceipt receipt: m_bc.receipts(h).receipts) auto receipts = m_bc.receipts(h).receipts;
if (_f.matches(info.logBloom))
for (size_t i = 0; i < receipts.size(); i++)
{ {
TransactionReceipt receipt = receipts[i];
if (_f.matches(receipt.bloom())) if (_f.matches(receipt.bloom()))
{ {
auto h = transaction(info.hash, i).sha3();
LogEntries le = _f.matches(receipt); LogEntries le = _f.matches(receipt);
if (le.size()) if (le.size())
{ {
@ -798,7 +808,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const
if (s) if (s)
s--; s--;
else else
ret.insert(ret.begin(), LocalisedLogEntry(le[j], n)); ret.insert(ret.begin(), LocalisedLogEntry(le[j], n, h));
} }
} }
} }

15
libethereum/Client.h

@ -27,7 +27,9 @@
#include <atomic> #include <atomic>
#include <string> #include <string>
#include <array> #include <array>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
@ -44,6 +46,7 @@
namespace dev namespace dev
{ {
namespace eth namespace eth
{ {
@ -166,7 +169,13 @@ class Client: public MinerHost, public Interface, Worker
public: public:
/// New-style Constructor. /// New-style Constructor.
explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0, int miners = -1); explicit Client(
p2p::Host* _host,
std::string const& _dbPath = std::string(),
bool _forceClean = false,
u256 _networkId = 0,
int _miners = -1
);
/// Destructor. /// Destructor.
virtual ~Client(); virtual ~Client();
@ -220,7 +229,7 @@ public:
/// @returns the length of the chain. /// @returns the length of the chain.
virtual unsigned number() const { return m_bc.number(); } virtual unsigned number() const { return m_bc.number(); }
/// Get a map containing each of the pending transactions. /// Get the list of pending transactions.
/// @TODO: Remove in favour of transactions(). /// @TODO: Remove in favour of transactions().
virtual Transactions pending() const { return m_postMine.pending(); } virtual Transactions pending() const { return m_postMine.pending(); }
@ -311,7 +320,7 @@ public:
protected: protected:
/// Collate the changed filters for the bloom filter of the given pending transaction. /// Collate the changed filters for the bloom filter of the given pending transaction.
/// Insert any filters that are activated into @a o_changed. /// Insert any filters that are activated into @a o_changed.
void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed); void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3);
/// Collate the changed filters for the hash of the given block. /// Collate the changed filters for the hash of the given block.
/// Insert any filters that are activated into @a o_changed. /// Insert any filters that are activated into @a o_changed.

1
libethereum/EthereumHost.h

@ -28,6 +28,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <thread> #include <thread>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>

4
libethereum/EthereumPeer.h

@ -26,6 +26,10 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>

1
libethereum/Miner.h

@ -32,6 +32,7 @@
namespace dev namespace dev
{ {
namespace eth namespace eth
{ {

7
libethereum/State.cpp

@ -27,6 +27,7 @@
#include <boost/timer.hpp> #include <boost/timer.hpp>
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/StructuredLogger.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
@ -820,6 +821,12 @@ void State::completeMine()
ret.swapOut(m_currentBytes); ret.swapOut(m_currentBytes);
m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data());
cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")";
StructuredLogger::minedNewBlock(
m_currentBlock.hash.abridged(),
m_currentBlock.nonce.abridged(),
"", //TODO: chain head hash here ??
m_currentBlock.parentHash.abridged()
);
// Quickly reset the transactions. // Quickly reset the transactions.
// TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo.

2
libethereumx/CMakeLists.txt

@ -30,6 +30,6 @@ target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
libevm/CMakeLists.txt

@ -34,6 +34,6 @@ if (EVMJIT)
target_link_libraries(${EXECUTABLE} evmjit-cpp) target_link_libraries(${EXECUTABLE} evmjit-cpp)
endif() endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

3
libevm/ExtVMFace.h

@ -63,9 +63,10 @@ using LogEntries = std::vector<LogEntry>;
struct LocalisedLogEntry: public LogEntry struct LocalisedLogEntry: public LogEntry
{ {
LocalisedLogEntry() {} LocalisedLogEntry() {}
LocalisedLogEntry(LogEntry const& _le, unsigned _number): LogEntry(_le), number(_number) {} LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _sha3 = {}): LogEntry(_le), number(_number), sha3(_sha3) {}
unsigned number = 0; unsigned number = 0;
h256 sha3;
}; };
using LocalisedLogEntries = std::vector<LocalisedLogEntry>; using LocalisedLogEntries = std::vector<LocalisedLogEntry>;

2
libevmcore/CMakeLists.txt

@ -26,6 +26,6 @@ endif()
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
libjsqrc/CMakeLists.txt

@ -22,4 +22,4 @@ if (ETH_NODE AND ETH_NPM)
add_dependencies(jsqrc ethereumjs) add_dependencies(jsqrc ethereumjs)
endif() endif()
install( TARGETS jsqrc ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS jsqrc RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )

9
libjsqrc/ethereumjs/README.md

@ -75,14 +75,13 @@ npm test
**Please note this repo is in it's early stage.** **Please note this repo is in it's early stage.**
If you'd like to run a WebSocket ethereum node check out If you'd like to run a Http ethereum node check out
[go-ethereum](https://github.com/ethereum/go-ethereum). [cpp-ethereum](https://github.com/ethereum/cpp-ethereum).
To install ethereum and spawn a node: Install ethereum and spawn a node:
``` ```
go get github.com/ethereum/go-ethereum/ethereum eth -j
ethereum -ws -loglevel=4
``` ```
[npm-image]: https://badge.fury.io/js/ethereum.js.png [npm-image]: https://badge.fury.io/js/ethereum.js.png

2
libjsqrc/ethereumjs/bower.json

@ -1,7 +1,7 @@
{ {
"name": "ethereum.js", "name": "ethereum.js",
"namespace": "ethereum", "namespace": "ethereum",
"version": "0.0.15", "version": "0.0.16",
"description": "Ethereum Compatible JavaScript API", "description": "Ethereum Compatible JavaScript API",
"main": [ "main": [
"./dist/ethereum.js", "./dist/ethereum.js",

114
libjsqrc/ethereumjs/dist/ethereum.js

@ -22,7 +22,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3');
var utils = require('./utils'); var utils = require('./utils');
var types = require('./types'); var types = require('./types');
var c = require('./const'); var c = require('./const');
@ -53,6 +52,8 @@ var inputTypes = types.inputTypes();
/// @returns bytes representation of input params /// @returns bytes representation of input params
var formatInput = function (inputs, params) { var formatInput = function (inputs, params) {
var bytes = ""; var bytes = "";
var toAppendConstant = "";
var toAppendArrayContent = "";
/// first we iterate in search for dynamic /// first we iterate in search for dynamic
inputs.forEach(function (input, index) { inputs.forEach(function (input, index) {
@ -60,6 +61,7 @@ var formatInput = function (inputs, params) {
}); });
inputs.forEach(function (input, i) { inputs.forEach(function (input, i) {
/*jshint maxcomplexity:5 */
var typeMatch = false; var typeMatch = false;
for (var j = 0; j < inputTypes.length && !typeMatch; j++) { for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
typeMatch = inputTypes[j].type(inputs[i].type, params[i]); typeMatch = inputTypes[j].type(inputs[i].type, params[i]);
@ -69,17 +71,19 @@ var formatInput = function (inputs, params) {
} }
var formatter = inputTypes[j - 1].format; var formatter = inputTypes[j - 1].format;
var toAppend = "";
if (arrayType(inputs[i].type)) if (arrayType(inputs[i].type))
toAppend = params[i].reduce(function (acc, curr) { toAppendArrayContent += params[i].reduce(function (acc, curr) {
return acc + formatter(curr); return acc + formatter(curr);
}, ""); }, "");
else if (inputs[i].type === 'string')
toAppendArrayContent += formatter(params[i]);
else else
toAppend = formatter(params[i]); toAppendConstant += formatter(params[i]);
bytes += toAppend;
}); });
bytes += toAppendConstant + toAppendArrayContent;
return bytes; return bytes;
}; };
@ -190,27 +194,14 @@ var outputParser = function (json) {
return parser; return parser;
}; };
/// @param function/event name for which we want to get signature
/// @returns signature of function/event with given name
var signatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);
};
var eventSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name));
};
module.exports = { module.exports = {
inputParser: inputParser, inputParser: inputParser,
outputParser: outputParser, outputParser: outputParser,
formatInput: formatInput, formatInput: formatInput,
formatOutput: formatOutput, formatOutput: formatOutput
signatureFromAscii: signatureFromAscii,
eventSignatureFromAscii: eventSignatureFromAscii
}; };
},{"./const":2,"./formatters":8,"./types":15,"./utils":16}],2:[function(require,module,exports){
},{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -296,6 +287,7 @@ var web3 = require('./web3');
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
var eventImpl = require('./event'); var eventImpl = require('./event');
var signature = require('./signature');
var exportNatspecGlobals = function (vars) { var exportNatspecGlobals = function (vars) {
// it's used byt natspec.js // it's used byt natspec.js
@ -343,12 +335,12 @@ var addFunctionsToContract = function (contract, desc, address) {
var impl = function () { var impl = function () {
/*jshint maxcomplexity:7 */ /*jshint maxcomplexity:7 */
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var signature = abi.signatureFromAscii(method.name); var sign = signature.functionSignatureFromAscii(method.name);
var parsed = inputParser[displayName][typeName].apply(null, params); var parsed = inputParser[displayName][typeName].apply(null, params);
var options = contract._options || {}; var options = contract._options || {};
options.to = address; options.to = address;
options.data = signature + parsed; options.data = sign + parsed;
var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant); var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);
var collapse = options.collapse !== false; var collapse = options.collapse !== false;
@ -402,7 +394,7 @@ var addEventRelatedPropertiesToContract = function (contract, desc, address) {
Object.defineProperty(contract, 'topic', { Object.defineProperty(contract, 'topic', {
get: function() { get: function() {
return utils.filterEvents(desc).map(function (e) { return utils.filterEvents(desc).map(function (e) {
return abi.eventSignatureFromAscii(e.name); return signature.eventSignatureFromAscii(e.name);
}); });
} }
}); });
@ -415,8 +407,8 @@ var addEventsToContract = function (contract, desc, address) {
var impl = function () { var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var signature = abi.eventSignatureFromAscii(e.name); var sign = signature.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e); var event = eventImpl.inputParser(address, sign, e);
var o = event.apply(null, params); var o = event.apply(null, params);
var outputFormatter = function (data) { var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e); var parser = eventImpl.outputParser(e);
@ -489,7 +481,7 @@ var contract = function (address, desc) {
module.exports = contract; module.exports = contract;
},{"./abi":1,"./event":6,"./utils":15,"./web3":17}],4:[function(require,module,exports){ },{"./abi":1,"./event":6,"./signature":14,"./utils":16,"./web3":18}],4:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -638,6 +630,7 @@ module.exports = {
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
var signature = require('./signature');
/// filter inputs array && returns only indexed (or not) inputs /// filter inputs array && returns only indexed (or not) inputs
/// @param inputs array /// @param inputs array
@ -676,14 +669,14 @@ var indexedParamsToTopics = function (event, indexed) {
}); });
}; };
var inputParser = function (address, signature, event) { var inputParser = function (address, sign, event) {
// valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'
return function (indexed, options) { return function (indexed, options) {
var o = options || {}; var o = options || {};
o.address = address; o.address = address;
o.topic = []; o.topic = [];
o.topic.push(signature); o.topic.push(sign);
if (indexed) { if (indexed) {
o.topic = o.topic.concat(indexedParamsToTopics(event, indexed)); o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));
} }
@ -712,6 +705,7 @@ var outputParser = function (event) {
var result = { var result = {
event: utils.extractDisplayName(event.name), event: utils.extractDisplayName(event.name),
number: output.number, number: output.number,
hash: output.hash,
args: {} args: {}
}; };
@ -735,8 +729,8 @@ var outputParser = function (event) {
var getMatchingEvent = function (events, payload) { var getMatchingEvent = function (events, payload) {
for (var i = 0; i < events.length; i++) { for (var i = 0; i < events.length; i++) {
var signature = abi.eventSignatureFromAscii(events[i].name); var sign = signature.eventSignatureFromAscii(events[i].name);
if (signature === payload.topic[0]) { if (sign === payload.topic[0]) {
return events[i]; return events[i];
} }
} }
@ -751,7 +745,7 @@ module.exports = {
}; };
},{"./abi":1,"./utils":15}],7:[function(require,module,exports){ },{"./abi":1,"./signature":14,"./utils":16}],7:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1023,7 +1017,7 @@ module.exports = {
}; };
},{"./const":2,"./utils":15}],9:[function(require,module,exports){ },{"./const":2,"./utils":16}],9:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1345,6 +1339,50 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file signature.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var web3 = require('./web3');
var c = require('./const');
/// @param function name for which we want to get signature
/// @returns signature of function with given name
var functionSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);
};
/// @param event name for which we want to get signature
/// @returns signature of event with given name
var eventSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name));
};
module.exports = {
functionSignatureFromAscii: functionSignatureFromAscii,
eventSignatureFromAscii: eventSignatureFromAscii
};
},{"./const":2,"./web3":18}],15:[function(require,module,exports){
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file types.js /** @file types.js
* @authors: * @authors:
* Marek Kotewicz <marek@ethdev.com> * Marek Kotewicz <marek@ethdev.com>
@ -1409,7 +1447,7 @@ module.exports = {
}; };
},{"./formatters":8}],15:[function(require,module,exports){ },{"./formatters":8}],16:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1554,7 +1592,7 @@ module.exports = {
}; };
},{"./const":2}],16:[function(require,module,exports){ },{"./const":2}],17:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1605,7 +1643,7 @@ module.exports = {
}; };
},{}],17:[function(require,module,exports){ },{}],18:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1796,7 +1834,7 @@ setupMethods(shhWatch, watches.shh());
module.exports = web3; module.exports = web3;
},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],"web3":[function(require,module,exports){ },{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":16,"./watches":17}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3'); var web3 = require('./lib/web3');
web3.providers.HttpSyncProvider = require('./lib/httpsync'); web3.providers.HttpSyncProvider = require('./lib/httpsync');
web3.providers.QtSyncProvider = require('./lib/qtsync'); web3.providers.QtSyncProvider = require('./lib/qtsync');
@ -1805,7 +1843,7 @@ web3.abi = require('./lib/abi');
module.exports = web3; module.exports = web3;
},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"]) },{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":18}]},{},["web3"])
//# sourceMappingURL=ethereum.js.map //# sourceMappingURL=ethereum.js.map

10
libjsqrc/ethereumjs/dist/ethereum.js.map

File diff suppressed because one or more lines are too long

2
libjsqrc/ethereumjs/dist/ethereum.min.js

File diff suppressed because one or more lines are too long

31
libjsqrc/ethereumjs/lib/abi.js

@ -21,7 +21,6 @@
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3');
var utils = require('./utils'); var utils = require('./utils');
var types = require('./types'); var types = require('./types');
var c = require('./const'); var c = require('./const');
@ -52,6 +51,8 @@ var inputTypes = types.inputTypes();
/// @returns bytes representation of input params /// @returns bytes representation of input params
var formatInput = function (inputs, params) { var formatInput = function (inputs, params) {
var bytes = ""; var bytes = "";
var toAppendConstant = "";
var toAppendArrayContent = "";
/// first we iterate in search for dynamic /// first we iterate in search for dynamic
inputs.forEach(function (input, index) { inputs.forEach(function (input, index) {
@ -59,6 +60,7 @@ var formatInput = function (inputs, params) {
}); });
inputs.forEach(function (input, i) { inputs.forEach(function (input, i) {
/*jshint maxcomplexity:5 */
var typeMatch = false; var typeMatch = false;
for (var j = 0; j < inputTypes.length && !typeMatch; j++) { for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
typeMatch = inputTypes[j].type(inputs[i].type, params[i]); typeMatch = inputTypes[j].type(inputs[i].type, params[i]);
@ -68,17 +70,19 @@ var formatInput = function (inputs, params) {
} }
var formatter = inputTypes[j - 1].format; var formatter = inputTypes[j - 1].format;
var toAppend = "";
if (arrayType(inputs[i].type)) if (arrayType(inputs[i].type))
toAppend = params[i].reduce(function (acc, curr) { toAppendArrayContent += params[i].reduce(function (acc, curr) {
return acc + formatter(curr); return acc + formatter(curr);
}, ""); }, "");
else if (inputs[i].type === 'string')
toAppendArrayContent += formatter(params[i]);
else else
toAppend = formatter(params[i]); toAppendConstant += formatter(params[i]);
bytes += toAppend;
}); });
bytes += toAppendConstant + toAppendArrayContent;
return bytes; return bytes;
}; };
@ -189,22 +193,9 @@ var outputParser = function (json) {
return parser; return parser;
}; };
/// @param function/event name for which we want to get signature
/// @returns signature of function/event with given name
var signatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);
};
var eventSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name));
};
module.exports = { module.exports = {
inputParser: inputParser, inputParser: inputParser,
outputParser: outputParser, outputParser: outputParser,
formatInput: formatInput, formatInput: formatInput,
formatOutput: formatOutput, formatOutput: formatOutput
signatureFromAscii: signatureFromAscii,
eventSignatureFromAscii: eventSignatureFromAscii
}; };

11
libjsqrc/ethereumjs/lib/contract.js

@ -24,6 +24,7 @@ var web3 = require('./web3');
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
var eventImpl = require('./event'); var eventImpl = require('./event');
var signature = require('./signature');
var exportNatspecGlobals = function (vars) { var exportNatspecGlobals = function (vars) {
// it's used byt natspec.js // it's used byt natspec.js
@ -71,12 +72,12 @@ var addFunctionsToContract = function (contract, desc, address) {
var impl = function () { var impl = function () {
/*jshint maxcomplexity:7 */ /*jshint maxcomplexity:7 */
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var signature = abi.signatureFromAscii(method.name); var sign = signature.functionSignatureFromAscii(method.name);
var parsed = inputParser[displayName][typeName].apply(null, params); var parsed = inputParser[displayName][typeName].apply(null, params);
var options = contract._options || {}; var options = contract._options || {};
options.to = address; options.to = address;
options.data = signature + parsed; options.data = sign + parsed;
var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant); var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);
var collapse = options.collapse !== false; var collapse = options.collapse !== false;
@ -130,7 +131,7 @@ var addEventRelatedPropertiesToContract = function (contract, desc, address) {
Object.defineProperty(contract, 'topic', { Object.defineProperty(contract, 'topic', {
get: function() { get: function() {
return utils.filterEvents(desc).map(function (e) { return utils.filterEvents(desc).map(function (e) {
return abi.eventSignatureFromAscii(e.name); return signature.eventSignatureFromAscii(e.name);
}); });
} }
}); });
@ -143,8 +144,8 @@ var addEventsToContract = function (contract, desc, address) {
var impl = function () { var impl = function () {
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var signature = abi.eventSignatureFromAscii(e.name); var sign = signature.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e); var event = eventImpl.inputParser(address, sign, e);
var o = event.apply(null, params); var o = event.apply(null, params);
var outputFormatter = function (data) { var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e); var parser = eventImpl.outputParser(e);

10
libjsqrc/ethereumjs/lib/event.js

@ -22,6 +22,7 @@
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
var signature = require('./signature');
/// filter inputs array && returns only indexed (or not) inputs /// filter inputs array && returns only indexed (or not) inputs
/// @param inputs array /// @param inputs array
@ -60,14 +61,14 @@ var indexedParamsToTopics = function (event, indexed) {
}); });
}; };
var inputParser = function (address, signature, event) { var inputParser = function (address, sign, event) {
// valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'
return function (indexed, options) { return function (indexed, options) {
var o = options || {}; var o = options || {};
o.address = address; o.address = address;
o.topic = []; o.topic = [];
o.topic.push(signature); o.topic.push(sign);
if (indexed) { if (indexed) {
o.topic = o.topic.concat(indexedParamsToTopics(event, indexed)); o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));
} }
@ -96,6 +97,7 @@ var outputParser = function (event) {
var result = { var result = {
event: utils.extractDisplayName(event.name), event: utils.extractDisplayName(event.name),
number: output.number, number: output.number,
hash: output.hash,
args: {} args: {}
}; };
@ -119,8 +121,8 @@ var outputParser = function (event) {
var getMatchingEvent = function (events, payload) { var getMatchingEvent = function (events, payload) {
for (var i = 0; i < events.length; i++) { for (var i = 0; i < events.length; i++) {
var signature = abi.eventSignatureFromAscii(events[i].name); var sign = signature.eventSignatureFromAscii(events[i].name);
if (signature === payload.topic[0]) { if (sign === payload.topic[0]) {
return events[i]; return events[i];
} }
} }

42
libjsqrc/ethereumjs/lib/signature.js

@ -0,0 +1,42 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file signature.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var web3 = require('./web3');
var c = require('./const');
/// @param function name for which we want to get signature
/// @returns signature of function with given name
var functionSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);
};
/// @param event name for which we want to get signature
/// @returns signature of event with given name
var eventSignatureFromAscii = function (name) {
return web3.sha3(web3.fromAscii(name));
};
module.exports = {
functionSignatureFromAscii: functionSignatureFromAscii,
eventSignatureFromAscii: eventSignatureFromAscii
};

2
libjsqrc/ethereumjs/package.json

@ -1,7 +1,7 @@
{ {
"name": "ethereum.js", "name": "ethereum.js",
"namespace": "ethereum", "namespace": "ethereum",
"version": "0.0.15", "version": "0.0.16",
"description": "Ethereum Compatible JavaScript API", "description": "Ethereum Compatible JavaScript API",
"main": "./index.js", "main": "./index.js",
"directories": { "directories": {

125
libjsqrc/ethereumjs/test/abi.inputParser.js

@ -309,7 +309,8 @@ describe('abi', function() {
// then // then
assert.equal( assert.equal(
parser.test('hello'), parser.test('hello'),
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000"
); );
assert.equal( assert.equal(
parser.test('world'), parser.test('world'),
@ -317,6 +318,50 @@ describe('abi', function() {
); );
}); });
it('should parse input int followed by a string', function () {
// given
var d = clone(description);
d[0].inputs = [
{ type: "int" },
{ type: "string" }
];
// when
var parser = abi.inputParser(d);
// then
assert.equal(
parser.test(9, 'hello'),
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000009" +
"68656c6c6f000000000000000000000000000000000000000000000000000000"
);
});
it('should parse input string followed by an int', function () {
// given
var d = clone(description);
d[0].inputs = [
{ type: "string" },
{ type: "int" }
];
// when
var parser = abi.inputParser(d);
// then
assert.equal(
parser.test('hello', 9),
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000009" +
"68656c6c6f000000000000000000000000000000000000000000000000000000"
);
});
it('should use proper method name', function () { it('should use proper method name', function () {
// given // given
@ -383,6 +428,83 @@ describe('abi', function() {
); );
}); });
it('should parse an array followed by an int', function () {
// given
var d = clone(description);
d[0].inputs = [
{ type: "int[]" },
{ type: "int" }
];
// when
var parser = abi.inputParser(d);
// then
assert.equal(
parser.test([5, 6], 3),
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000003" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006"
);
});
it('should parse an int followed by an array', function () {
// given
var d = clone(description);
d[0].inputs = [
{ type: "int" },
{ type: "int[]" }
];
// when
var parser = abi.inputParser(d);
// then
assert.equal(
parser.test(3, [5, 6]),
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000003" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006"
);
});
it('should parse mixture of arrays and ints', function () {
// given
var d = clone(description);
d[0].inputs = [
{ type: "int" },
{ type: "int[]" },
{ type: "int" },
{ type: "int[]" }
];
// when
var parser = abi.inputParser(d);
// then
assert.equal(
parser.test(3, [5, 6, 1, 2], 7, [8, 9]),
"0000000000000000000000000000000000000000000000000000000000000004" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000003" +
"0000000000000000000000000000000000000000000000000000000000000007" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006" +
"0000000000000000000000000000000000000000000000000000000000000001" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000008" +
"0000000000000000000000000000000000000000000000000000000000000009"
);
});
it('should parse input real', function () { it('should parse input real', function () {
// given // given
@ -424,4 +546,3 @@ describe('abi', function() {
}); });
}); });

2
liblll/CMakeLists.txt

@ -27,6 +27,6 @@ endif()
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

3
libnatspec/CMakeLists.txt

@ -14,6 +14,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE natspec) set(EXECUTABLE natspec)
@ -31,5 +32,5 @@ target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Qml) target_link_libraries(${EXECUTABLE} Qt5::Qml)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

7
libp2p/CMakeLists.txt

@ -15,6 +15,7 @@ include_directories(BEFORE ..)
# we may not use it in libp2p, but one of our dependecies is including leveldb in header file # we may not use it in libp2p, but one of our dependecies is including leveldb in header file
# and windows is failing to build without that # and windows is failing to build without that
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
if (MINIUPNPC_FOUND) if (MINIUPNPC_FOUND)
include_directories(${MINIUPNPC_INCLUDE_DIRS}) include_directories(${MINIUPNPC_INCLUDE_DIRS})
@ -37,6 +38,10 @@ endif()
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) if (CMAKE_COMPILER_IS_MINGW)
target_link_libraries(${EXECUTABLE} ws2_32 mswsock)
endif()
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

3
libp2p/Common.h

@ -27,8 +27,11 @@
#include <string> #include <string>
#include <set> #include <set>
#include <vector> #include <vector>
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <chrono> #include <chrono>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>

11
libp2p/Host.cpp

@ -24,9 +24,12 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/StructuredLogger.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include "Session.h" #include "Session.h"
@ -158,6 +161,13 @@ void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
{ {
{ {
clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged(); clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged();
StructuredLogger::p2pConnected(
_s->m_peer->id.abridged(),
_s->m_peer->peerEndpoint(),
_s->m_peer->m_lastConnected,
_s->m_info.clientVersion,
peerCount()
);
RecursiveGuard l(x_sessions); RecursiveGuard l(x_sessions);
// TODO: temporary loose-coupling; if m_peers already has peer, // TODO: temporary loose-coupling; if m_peers already has peer,
// it is same as _s->m_peer. (fixing next PR) // it is same as _s->m_peer. (fixing next PR)
@ -474,6 +484,7 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
_p->m_lastDisconnect = NoDisconnect; _p->m_lastDisconnect = NoDisconnect;
_p->m_lastConnected = std::chrono::system_clock::now(); _p->m_lastConnected = std::chrono::system_clock::now();
_p->m_failedAttempts = 0; _p->m_failedAttempts = 0;
auto ps = make_shared<Session>(this, std::move(*s), _p); auto ps = make_shared<Session>(this, std::move(*s), _p);
ps->start(); ps->start();

8
libp2p/Host.h

@ -30,6 +30,7 @@
#include <utility> #include <utility>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>
@ -85,7 +86,11 @@ class Host: public Worker
public: public:
/// Start server, listening for connections on the given port. /// Start server, listening for connections on the given port.
Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bytesConstRef _restoreNetwork = bytesConstRef()); Host(
std::string const& _clientVersion,
NetworkPreferences const& _n = NetworkPreferences(),
bytesConstRef _restoreNetwork = bytesConstRef()
);
/// Will block on network process events. /// Will block on network process events.
virtual ~Host(); virtual ~Host();
@ -232,7 +237,6 @@ private:
std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities; ///< Each of the capabilities we support. std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities; ///< Each of the capabilities we support.
std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers.
bool m_accepting = false; bool m_accepting = false;
}; };

1
libp2p/Network.cpp

@ -27,6 +27,7 @@
#endif #endif
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>

2
libp2p/NodeTable.h

@ -23,7 +23,9 @@
#include <algorithm> #include <algorithm>
#include <deque> #include <deque>
#include <boost/integer/static_log2.hpp> #include <boost/integer/static_log2.hpp>
#include <libp2p/UDP.h> #include <libp2p/UDP.h>
#include "Common.h" #include "Common.h"

6
libp2p/Session.cpp

@ -24,6 +24,7 @@
#include <chrono> #include <chrono>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/StructuredLogger.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include "Host.h" #include "Host.h"
#include "Capability.h" #include "Capability.h"
@ -467,6 +468,11 @@ void Session::drop(DisconnectReason _reason)
void Session::disconnect(DisconnectReason _reason) void Session::disconnect(DisconnectReason _reason)
{ {
clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")";
StructuredLogger::p2pDisconnected(
m_info.id.abridged(),
m_peer->peerEndpoint(),
m_server->peerCount()
);
if (m_socket.is_open()) if (m_socket.is_open())
{ {
RLPStream s; RLPStream s;

1
libp2p/Session.h

@ -27,6 +27,7 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>

1
libp2p/UDP.h

@ -26,6 +26,7 @@
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <array> #include <array>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>

2
libserpent/CMakeLists.txt

@ -27,6 +27,6 @@ target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
libsolidity/CMakeLists.txt

@ -30,6 +30,6 @@ target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

67
libsolidity/Compiler.cpp

@ -205,42 +205,49 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool
{ {
// We do not check the calldata size, everything is zero-padded. // We do not check the calldata size, everything is zero-padded.
unsigned offset(CompilerUtils::dataStartOffset); unsigned offset(CompilerUtils::dataStartOffset);
bool const c_padToWords = true;
unsigned dynamicParameterCount = 0; bigint parameterHeadEnd = offset;
for (TypePointer const& type: _typeParameters) for (TypePointer const& type: _typeParameters)
if (type->isDynamicallySized()) parameterHeadEnd += type->isDynamicallySized() ? 32 :
dynamicParameterCount++; CompilerUtils::getPaddedSize(type->getCalldataEncodedSize());
offset += dynamicParameterCount * 32; solAssert(parameterHeadEnd <= numeric_limits<unsigned>::max(), "Arguments too large.");
unsigned currentDynamicParameter = 0;
unsigned stackHeightOfPreviousDynamicArgument = 0;
ArrayType const* previousDynamicType = nullptr;
for (TypePointer const& type: _typeParameters) for (TypePointer const& type: _typeParameters)
if (type->isDynamicallySized()) {
switch (type->getCategory())
{ {
// value on stack: [calldata_offset] (only if we are already in dynamic mode) case Type::Category::Array:
if (currentDynamicParameter == 0) if (type->isDynamicallySized())
// switch from static to dynamic {
// put on stack: data_offset length
unsigned newStackHeight = m_context.getStackHeight();
if (previousDynamicType)
{
// Retrieve data start offset by adding length to start offset of previous dynamic type
unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument;
m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth);
ArrayUtils(m_context).convertLengthToSize(*previousDynamicType);
m_context << u256(32) << eth::Instruction::MUL << eth::Instruction::ADD;
}
else
m_context << u256(parameterHeadEnd);
stackHeightOfPreviousDynamicArgument = newStackHeight;
previousDynamicType = &dynamic_cast<ArrayType const&>(*type);
offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory);
}
else
{
m_context << u256(offset); m_context << u256(offset);
// retrieve length offset += CompilerUtils::getPaddedSize(type->getCalldataEncodedSize());
CompilerUtils(m_context).loadFromMemory( }
CompilerUtils::dataStartOffset + currentDynamicParameter * 32, break;
IntegerType(256), !_fromMemory, c_padToWords); default:
// stack: offset length solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString());
// add 32-byte padding to copy of length offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true);
m_context << u256(32) << eth::Instruction::DUP1 << u256(31)
<< eth::Instruction::DUP4 << eth::Instruction::ADD
<< eth::Instruction::DIV << eth::Instruction::MUL;
// stack: offset length padded_length
m_context << eth::Instruction::DUP3 << eth::Instruction::ADD;
currentDynamicParameter++;
// stack: offset length next_calldata_offset
} }
else if (currentDynamicParameter == 0) }
// we can still use static load
offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords);
else
CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords);
if (dynamicParameterCount > 0)
m_context << eth::Instruction::POP;
} }
void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters)

17
libsolidity/ExpressionCompiler.cpp

@ -984,9 +984,10 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
else else
// send all gas except for the 21 needed to execute "SUB" and "CALL" // send all gas except for the 21 needed to execute "SUB" and "CALL"
m_context << u256(21) << eth::Instruction::GAS << eth::Instruction::SUB; m_context << u256(_functionType.valueSet() ? 6741 : 41) << eth::Instruction::GAS << eth::Instruction::SUB;
m_context << eth::Instruction::CALL m_context << eth::Instruction::CALL;
<< eth::Instruction::POP; // @todo do not ignore failure indicator auto tag = m_context.appendConditionalJump();
m_context << eth::Instruction::STOP << tag; // STOP if CALL leaves 0.
if (_functionType.valueSet()) if (_functionType.valueSet())
m_context << eth::Instruction::POP; m_context << eth::Instruction::POP;
if (_functionType.gasSet()) if (_functionType.gasSet())
@ -999,10 +1000,12 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true); CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true);
} }
void ExpressionCompiler::appendArgumentsCopyToMemory(vector<ASTPointer<Expression const>> const& _arguments, void ExpressionCompiler::appendArgumentsCopyToMemory(
TypePointers const& _types, vector<ASTPointer<Expression const>> const& _arguments,
bool _padToWordBoundaries, TypePointers const& _types,
bool _padExceptionIfFourBytes) bool _padToWordBoundaries,
bool _padExceptionIfFourBytes
)
{ {
solAssert(_types.empty() || _types.size() == _arguments.size(), ""); solAssert(_types.empty() || _types.size() == _arguments.size(), "");
for (size_t i = 0; i < _arguments.size(); ++i) for (size_t i = 0; i < _arguments.size(); ++i)

1
libsolidity/Token.h

@ -46,6 +46,7 @@
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libsolidity/Utils.h> #include <libsolidity/Utils.h>
#include <libsolidity/Exceptions.h> #include <libsolidity/Exceptions.h>
#include <libdevcore/UndefMacros.h>
namespace dev namespace dev
{ {

13
libsolidity/Types.cpp

@ -570,6 +570,15 @@ bool ArrayType::operator==(Type const& _other) const
return isDynamicallySized() || getLength() == other.getLength(); return isDynamicallySized() || getLength() == other.getLength();
} }
unsigned ArrayType::getCalldataEncodedSize() const
{
if (isDynamicallySized())
return 0;
bigint size = bigint(getLength()) * (isByteArray() ? 1 : getBaseType()->getCalldataEncodedSize());
solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
return unsigned(size);
}
u256 ArrayType::getStorageSize() const u256 ArrayType::getStorageSize() const
{ {
if (isDynamicallySized()) if (isDynamicallySized())
@ -586,8 +595,8 @@ u256 ArrayType::getStorageSize() const
unsigned ArrayType::getSizeOnStack() const unsigned ArrayType::getSizeOnStack() const
{ {
if (m_location == Location::CallData) if (m_location == Location::CallData)
// offset, length (stack top) // offset [length] (stack top)
return 2; return 1 + (isDynamicallySized() ? 1 : 0);
else else
// offset // offset
return 1; return 1;

3
libsolidity/Types.h

@ -30,6 +30,7 @@
#include <libsolidity/Exceptions.h> #include <libsolidity/Exceptions.h>
#include <libsolidity/ASTForward.h> #include <libsolidity/ASTForward.h>
#include <libsolidity/Token.h> #include <libsolidity/Token.h>
#include <libdevcore/UndefMacros.h>
namespace dev namespace dev
{ {
@ -67,7 +68,6 @@ private:
MemberMap m_memberTypes; MemberMap m_memberTypes;
}; };
/** /**
* Abstract base class that forms the root of the type hierarchy. * Abstract base class that forms the root of the type hierarchy.
*/ */
@ -302,6 +302,7 @@ public:
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual bool operator==(const Type& _other) const override; virtual bool operator==(const Type& _other) const override;
virtual unsigned getCalldataEncodedSize() const override;
virtual bool isDynamicallySized() const { return m_hasDynamicLength; } virtual bool isDynamicallySized() const { return m_hasDynamicLength; }
virtual u256 getStorageSize() const override; virtual u256 getStorageSize() const override;
virtual unsigned getSizeOnStack() const override; virtual unsigned getSizeOnStack() const override;

3
libweb3jsonrpc/CMakeLists.txt

@ -14,6 +14,7 @@ include_directories(BEFORE ..)
include_directories(${MHD_INCLUDE_DIRS}) include_directories(${MHD_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE web3jsonrpc) set(EXECUTABLE web3jsonrpc)
@ -52,7 +53,7 @@ if (ETH_JSON_RPC_STUB)
add_dependencies(${EXECUTABLE} jsonrpcstub) add_dependencies(${EXECUTABLE} jsonrpcstub)
endif() endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

3
libweb3jsonrpc/WebThreeStubServer.cpp

@ -21,7 +21,10 @@
* @date 2014 * @date 2014
*/ */
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include "WebThreeStubServer.h" #include "WebThreeStubServer.h"

4
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -21,6 +21,9 @@
* @date 2014 * @date 2014
*/ */
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <libsolidity/CompilerStack.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
@ -95,6 +98,7 @@ static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e)
for (auto const& t: _e.topics) for (auto const& t: _e.topics)
res["topic"].append(toJS(t)); res["topic"].append(toJS(t));
res["number"] = _e.number; res["number"] = _e.number;
res["hash"] = toJS(_e.sha3);
return res; return res;
} }

3
libwebthree/CMakeLists.txt

@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE webthree) set(EXECUTABLE webthree)
@ -35,6 +36,6 @@ target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

14
libwebthree/WebThree.cpp

@ -23,7 +23,9 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libp2p/Host.h> #include <libp2p/Host.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
@ -35,15 +37,21 @@ using namespace dev::p2p;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::shh; using namespace dev::shh;
WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set<std::string> const& _interfaces, NetworkPreferences const& _n, bytesConstRef _network, int miners): WebThreeDirect::WebThreeDirect(
std::string const& _clientVersion,
std::string const& _dbPath,
bool _forceClean,
std::set<std::string> const& _interfaces,
NetworkPreferences const& _n,
bytesConstRef _network, int _miners
):
m_clientVersion(_clientVersion), m_clientVersion(_clientVersion),
m_net(_clientVersion, _n, _network) m_net(_clientVersion, _n, _network)
{ {
if (_dbPath.size()) if (_dbPath.size())
Defaults::setDBPath(_dbPath); Defaults::setDBPath(_dbPath);
if (_interfaces.count("eth")) if (_interfaces.count("eth"))
m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, miners)); m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners));
if (_interfaces.count("shh")) if (_interfaces.count("shh"))
m_whisper = m_net.registerCapability<WhisperHost>(new WhisperHost); m_whisper = m_net.registerCapability<WhisperHost>(new WhisperHost);

14
libwebthree/WebThree.h

@ -25,7 +25,11 @@
#include <mutex> #include <mutex>
#include <list> #include <list>
#include <atomic> #include <atomic>
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
@ -103,7 +107,15 @@ class WebThreeDirect : public WebThreeNetworkFace
public: public:
/// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception. /// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception.
/// ethereum() may be safely static_cast()ed to a eth::Client*. /// ethereum() may be safely static_cast()ed to a eth::Client*.
WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set<std::string> const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), bytesConstRef _network = bytesConstRef(), int miners = -1); WebThreeDirect(
std::string const& _clientVersion,
std::string const& _dbPath,
bool _forceClean = false,
std::set<std::string> const& _interfaces = {"eth", "shh"},
p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(),
bytesConstRef _network = bytesConstRef(),
int _miners = -1
);
/// Destructor. /// Destructor.
~WebThreeDirect(); ~WebThreeDirect();

3
libwhisper/CMakeLists.txt

@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE whisper) set(EXECUTABLE whisper)
@ -32,5 +33,5 @@ target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} p2p)
target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} secp256k1)
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

1
libwhisper/Common.h

@ -23,6 +23,7 @@
#include <string> #include <string>
#include <chrono> #include <chrono>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>

1
libwhisper/Interface.h

@ -26,6 +26,7 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>

1
libwhisper/Message.h

@ -26,6 +26,7 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>

4
libwhisper/WhisperHost.cpp

@ -58,7 +58,7 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
{ {
cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data()); cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data());
if (_m.expiry() <= time(0)) if (_m.expiry() <= (unsigned)time(0))
return; return;
auto h = _m.sha3(); auto h = _m.sha3();
@ -171,7 +171,7 @@ void WhisperHost::cleanup()
{ {
// remove old messages. // remove old messages.
// should be called every now and again. // should be called every now and again.
auto now = time(0); unsigned now = (unsigned)time(0);
WriteGuard l(x_messages); WriteGuard l(x_messages);
for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it)) for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it))
m_messages.erase(it->second); m_messages.erase(it->second);

1
libwhisper/WhisperHost.h

@ -26,6 +26,7 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>

1
libwhisper/WhisperPeer.h

@ -26,6 +26,7 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>

1
mix/CMakeLists.txt

@ -12,6 +12,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
include_directories(BEFORE ..) include_directories(BEFORE ..)
find_package (Qt5WebEngine QUIET) find_package (Qt5WebEngine QUIET)

41
mix/ClientModel.cpp

@ -18,6 +18,9 @@
* Ethereum IDE client. * Ethereum IDE client.
*/ */
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include <QDebug> #include <QDebug>
#include <QQmlContext> #include <QQmlContext>
@ -38,6 +41,7 @@
#include "Web3Server.h" #include "Web3Server.h"
#include "MixClient.h" #include "MixClient.h"
#include "ClientModel.h" #include "ClientModel.h"
#include "MixClient.h"
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -87,7 +91,7 @@ ClientModel::ClientModel(AppContext* _context):
connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection);
m_client.reset(new MixClient(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString())); m_client.reset(new MixClient(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString()));
m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), std::vector<dev::KeyPair> { m_client->userAccount() }, m_client.get())); m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), m_client->userAccounts(), m_client.get()));
connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection); connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection);
_context->appEngine()->rootContext()->setContextProperty("clientModel", this); _context->appEngine()->rootContext()->setContextProperty("clientModel", this);
} }
@ -136,6 +140,12 @@ void ClientModel::mine()
}); });
} }
QString ClientModel::newAddress()
{
KeyPair a = KeyPair::create();
return QString::fromStdString(toHex(a.secret().ref()));
}
QVariantMap ClientModel::contractAddresses() const QVariantMap ClientModel::contractAddresses() const
{ {
QVariantMap res; QVariantMap res;
@ -144,16 +154,18 @@ QVariantMap ClientModel::contractAddresses() const
return res; return res;
} }
void ClientModel::debugDeployment()
{
executeSequence(std::vector<TransactionSettings>(), 10000000 * ether);
}
void ClientModel::setupState(QVariantMap _state) void ClientModel::setupState(QVariantMap _state)
{ {
u256 balance = (qvariant_cast<QEther*>(_state.value("balance")))->toU256Wei(); QVariantList balances = _state.value("accounts").toList();
QVariantList transactions = _state.value("transactions").toList(); QVariantList transactions = _state.value("transactions").toList();
std::map<Secret, u256> accounts;
for (auto const& b: balances)
{
QVariantMap address = b.toMap();
accounts.insert(std::make_pair(Secret(address.value("secret").toString().toStdString()), (qvariant_cast<QEther*>(address.value("balance")))->toU256Wei()));
}
std::vector<TransactionSettings> transactionSequence; std::vector<TransactionSettings> transactionSequence;
for (auto const& t: transactions) for (auto const& t: transactions)
{ {
@ -163,7 +175,7 @@ void ClientModel::setupState(QVariantMap _state)
u256 gas = boost::get<u256>(qvariant_cast<QBigInt*>(transaction.value("gas"))->internalValue()); u256 gas = boost::get<u256>(qvariant_cast<QBigInt*>(transaction.value("gas"))->internalValue());
u256 value = (qvariant_cast<QEther*>(transaction.value("value")))->toU256Wei(); u256 value = (qvariant_cast<QEther*>(transaction.value("value")))->toU256Wei();
u256 gasPrice = (qvariant_cast<QEther*>(transaction.value("gasPrice")))->toU256Wei(); u256 gasPrice = (qvariant_cast<QEther*>(transaction.value("gasPrice")))->toU256Wei();
QString sender = transaction.value("sender").toString();
bool isStdContract = (transaction.value("stdContract").toBool()); bool isStdContract = (transaction.value("stdContract").toBool());
if (isStdContract) if (isStdContract)
{ {
@ -173,6 +185,7 @@ void ClientModel::setupState(QVariantMap _state)
transactionSettings.gasPrice = 10000000000000; transactionSettings.gasPrice = 10000000000000;
transactionSettings.gas = 125000; transactionSettings.gas = 125000;
transactionSettings.value = 0; transactionSettings.value = 0;
transactionSettings.sender = Secret(sender.toStdString());
transactionSequence.push_back(transactionSettings); transactionSequence.push_back(transactionSettings);
} }
else else
@ -180,7 +193,7 @@ void ClientModel::setupState(QVariantMap _state)
if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later
contractId = m_context->codeModel()->contracts().keys()[0]; contractId = m_context->codeModel()->contracts().keys()[0];
QVariantList qParams = transaction.value("qType").toList(); QVariantList qParams = transaction.value("qType").toList();
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice); TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString()));
for (QVariant const& variant: qParams) for (QVariant const& variant: qParams)
{ {
@ -194,10 +207,10 @@ void ClientModel::setupState(QVariantMap _state)
transactionSequence.push_back(transactionSettings); transactionSequence.push_back(transactionSettings);
} }
} }
executeSequence(transactionSequence, balance); executeSequence(transactionSequence, accounts);
} }
void ClientModel::executeSequence(std::vector<TransactionSettings> const& _sequence, u256 _balance) void ClientModel::executeSequence(std::vector<TransactionSettings> const& _sequence, std::map<Secret, u256> const& _balances)
{ {
if (m_running) if (m_running)
BOOST_THROW_EXCEPTION(ExecutionStateException()); BOOST_THROW_EXCEPTION(ExecutionStateException());
@ -211,7 +224,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
{ {
try try
{ {
m_client->resetState(_balance); m_client->resetState(_balances);
onStateReset(); onStateReset();
for (TransactionSettings const& transaction: _sequence) for (TransactionSettings const& transaction: _sequence)
{ {
@ -425,13 +438,13 @@ void ClientModel::showDebugError(QString const& _error)
Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction)
{ {
Address newAddress = m_client->transact(m_client->userAccount().secret(), _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice); Address newAddress = m_client->transact(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice);
return newAddress; return newAddress;
} }
void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr)
{ {
m_client->transact(m_client->userAccount().secret(), _tr.value, _contract, _data, _tr.gas, _tr.gasPrice); m_client->transact(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice);
} }
RecordLogEntry* ClientModel::lastBlock() const RecordLogEntry* ClientModel::lastBlock() const

11
mix/ClientModel.h

@ -47,8 +47,8 @@ struct SolidityType;
struct TransactionSettings struct TransactionSettings
{ {
TransactionSettings() {} TransactionSettings() {}
TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice): TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice, Secret _sender):
contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {} contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice), sender(_sender) {}
TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl):
contractId(_stdContractName), stdContractUrl(_stdContractUrl) {} contractId(_stdContractName), stdContractUrl(_stdContractUrl) {}
@ -66,6 +66,8 @@ struct TransactionSettings
QList<QVariableDefinition*> parameterValues; QList<QVariableDefinition*> parameterValues;
/// Standard contract url /// Standard contract url
QString stdContractUrl; QString stdContractUrl;
/// Sender
Secret sender;
}; };
@ -143,8 +145,6 @@ public:
Q_INVOKABLE void mine(); Q_INVOKABLE void mine();
public slots: public slots:
/// Run the contract constructor and show debugger window.
void debugDeployment();
/// Setup state, run transaction sequence, show debugger for the last transaction /// Setup state, run transaction sequence, show debugger for the last transaction
/// @param _state JS object with state configuration /// @param _state JS object with state configuration
void setupState(QVariantMap _state); void setupState(QVariantMap _state);
@ -152,6 +152,7 @@ public slots:
Q_INVOKABLE void debugRecord(unsigned _index); Q_INVOKABLE void debugRecord(unsigned _index);
/// Show the debugger for an empty record /// Show the debugger for an empty record
Q_INVOKABLE void emptyRecord(); Q_INVOKABLE void emptyRecord();
Q_INVOKABLE QString newAddress();
private slots: private slots:
/// Update UI with machine states result. Display a modal dialog. /// Update UI with machine states result. Display a modal dialog.
@ -192,7 +193,7 @@ signals:
private: private:
RecordLogEntry* lastBlock() const; RecordLogEntry* lastBlock() const;
QVariantMap contractAddresses() const; QVariantMap contractAddresses() const;
void executeSequence(std::vector<TransactionSettings> const& _sequence, u256 _balance); void executeSequence(std::vector<TransactionSettings> const& _sequence, std::map<Secret, u256> const& _balances);
dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings());
void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr);
void onNewTransaction(); void onNewTransaction();

3
mix/DebuggingStateWrapper.h

@ -22,6 +22,9 @@
#pragma once #pragma once
// Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp>
#include <QStringList> #include <QStringList>
#include <QHash> #include <QHash>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>

3
mix/Extension.cpp

@ -17,13 +17,16 @@
* Ethereum IDE client. * Ethereum IDE client.
*/ */
#include <QMessageBox> #include <QMessageBox>
#include <QDebug> #include <QDebug>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#include "Extension.h" #include "Extension.h"
#include "AppContext.h" #include "AppContext.h"
using namespace dev; using namespace dev;
using namespace dev::mix; using namespace dev::mix;

22
mix/MixClient.cpp

@ -40,7 +40,7 @@ namespace dev
namespace mix namespace mix
{ {
const Secret c_userAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074");
const u256 c_mixGenesisDifficulty = (u256) 1 << 4; const u256 c_mixGenesisDifficulty = (u256) 1 << 4;
class MixBlockChain: public dev::eth::BlockChain class MixBlockChain: public dev::eth::BlockChain
@ -62,16 +62,18 @@ public:
}; };
MixClient::MixClient(std::string const& _dbPath): MixClient::MixClient(std::string const& _dbPath):
m_userAccount(c_userAccountSecret), m_dbPath(_dbPath), m_minigThreads(0) m_dbPath(_dbPath), m_minigThreads(0)
{ {
resetState(10000000 * ether); std::map<Secret, u256> account;
account.insert(std::make_pair(c_defaultUserAccountSecret, 1000000 * ether));
resetState(account);
} }
MixClient::~MixClient() MixClient::~MixClient()
{ {
} }
void MixClient::resetState(u256 _balance) void MixClient::resetState(std::map<Secret, u256> _accounts)
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
Guard fl(m_filterLock); Guard fl(m_filterLock);
@ -81,12 +83,20 @@ void MixClient::resetState(u256 _balance)
m_stateDB = OverlayDB(); m_stateDB = OverlayDB();
TrieDB<Address, MemoryDB> accountState(&m_stateDB); TrieDB<Address, MemoryDB> accountState(&m_stateDB);
accountState.init(); accountState.init();
std::map<Address, Account> genesisState = { std::make_pair(KeyPair(c_userAccountSecret).address(), Account(_balance, Account::NormalCreation)) };
std::map<Address, Account> genesisState;
for (auto account: _accounts)
{
KeyPair a = KeyPair(account.first);
m_userAccounts.push_back(a);
genesisState.insert(std::make_pair(a.address(), Account(account.second, Account::NormalCreation)));
}
dev::eth::commit(genesisState, static_cast<MemoryDB&>(m_stateDB), accountState); dev::eth::commit(genesisState, static_cast<MemoryDB&>(m_stateDB), accountState);
h256 stateRoot = accountState.root(); h256 stateRoot = accountState.root();
m_bc.reset(); m_bc.reset();
m_bc.reset(new MixBlockChain(m_dbPath, stateRoot)); m_bc.reset(new MixBlockChain(m_dbPath, stateRoot));
m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty); m_state = eth::State(genesisState.begin()->first , m_stateDB, BaseState::Empty);
m_state.sync(bc()); m_state.sync(bc());
m_startState = m_state; m_startState = m_state;
m_executions.clear(); m_executions.clear();

6
mix/MixClient.h

@ -42,8 +42,7 @@ public:
MixClient(std::string const& _dbPath); MixClient(std::string const& _dbPath);
virtual ~MixClient(); virtual ~MixClient();
/// Reset state to the empty state with given balance. /// Reset state to the empty state with given balance.
void resetState(u256 _balance); void resetState(std::map<Secret, u256> _accounts);
KeyPair const& userAccount() const { return m_userAccount; }
void mine(); void mine();
ExecutionResult const& lastExecution() const; ExecutionResult const& lastExecution() const;
ExecutionResults const& executions() const; ExecutionResults const& executions() const;
@ -91,6 +90,7 @@ public:
bool submitNonce(h256 const&) override { return false; } bool submitNonce(h256 const&) override { return false; }
/// @returns the last mined block information /// @returns the last mined block information
eth::BlockInfo blockInfo() const; eth::BlockInfo blockInfo() const;
std::vector<KeyPair> userAccounts() { return m_userAccounts; }
private: private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call); void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call);
@ -99,7 +99,7 @@ private:
MixBlockChain& bc() { return *m_bc; } MixBlockChain& bc() { return *m_bc; }
MixBlockChain const& bc() const { return *m_bc; } MixBlockChain const& bc() const { return *m_bc; }
KeyPair m_userAccount; std::vector<KeyPair> m_userAccounts;
eth::State m_state; eth::State m_state;
eth::State m_startState; eth::State m_startState;
OverlayDB m_stateDB; OverlayDB m_stateDB;

1
mix/QContractDefinition.cpp

@ -20,6 +20,7 @@
*/ */
#include <QObject> #include <QObject>
#include <libsolidity/CompilerStack.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>

4
mix/qml/Ether.qml

@ -20,7 +20,7 @@ RowLayout {
function update() function update()
{ {
if (value !== undefined) if (value)
{ {
etherValueEdit.text = value.value; etherValueEdit.text = value.value;
selectUnit(value.unit); selectUnit(value.unit);
@ -54,7 +54,7 @@ RowLayout {
id: units id: units
onCurrentTextChanged: onCurrentTextChanged:
{ {
if (value !== undefined) if (value)
{ {
value.setUnit(currentText); value.setUnit(currentText);
formattedValue.text = value.format(); formattedValue.text = value.format();

151
mix/qml/StateDialog.qml

@ -1,5 +1,6 @@
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Controls 1.1 import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Window 2.0 import QtQuick.Window 2.0
import QtQuick.Controls.Styles 1.3 import QtQuick.Controls.Styles 1.3
@ -12,24 +13,24 @@ Window {
id: modalStateDialog id: modalStateDialog
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
width: 520 width: 590
height: 480 height: 480
title: qsTr("Edit State") title: qsTr("Edit State")
visible: false visible: false
color: StateDialogStyle.generic.backgroundColor color: StateDialogStyle.generic.backgroundColor
property alias stateTitle: titleField.text property alias stateTitle: titleField.text
property alias stateBalance: balanceField.value
property alias isDefault: defaultCheckBox.checked property alias isDefault: defaultCheckBox.checked
property int stateIndex property int stateIndex
property var stateTransactions: [] property var stateTransactions: []
property var stateAccounts: []
signal accepted signal accepted
function open(index, item, setDefault) { function open(index, item, setDefault) {
stateIndex = index; stateIndex = index;
stateTitle = item.title; stateTitle = item.title;
balanceField.value = item.balance;
transactionsModel.clear(); transactionsModel.clear();
stateTransactions = []; stateTransactions = [];
var transactions = item.transactions; var transactions = item.transactions;
for (var t = 0; t < transactions.length; t++) { for (var t = 0; t < transactions.length; t++) {
@ -37,6 +38,14 @@ Window {
stateTransactions.push(item.transactions[t]); stateTransactions.push(item.transactions[t]);
} }
accountsModel.clear();
stateAccounts = [];
for (var k = 0; k < item.accounts.length; k++)
{
accountsModel.append(item.accounts[k]);
stateAccounts.push(item.accounts[k]);
}
modalStateDialog.setX((Screen.width - width) / 2); modalStateDialog.setX((Screen.width - width) / 2);
modalStateDialog.setY((Screen.height - height) / 2); modalStateDialog.setY((Screen.height - height) / 2);
@ -54,10 +63,11 @@ Window {
function getItem() { function getItem() {
var item = { var item = {
title: stateDialog.stateTitle, title: stateDialog.stateTitle,
balance: stateDialog.stateBalance, transactions: [],
transactions: [] accounts: []
} }
item.transactions = stateTransactions; item.transactions = stateTransactions;
item.accounts = stateAccounts;
return item; return item;
} }
@ -90,15 +100,112 @@ Window {
RowLayout RowLayout
{ {
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel {
Rectangle
{
Layout.preferredWidth: 75 Layout.preferredWidth: 75
text: qsTr("Balance") DefaultLabel {
id: accountsLabel
Layout.preferredWidth: 75
text: qsTr("Accounts")
}
Button
{
anchors.top: accountsLabel.bottom
anchors.topMargin: 10
iconSource: "qrc:/qml/img/plus.png"
action: newAccountAction
}
Action {
id: newAccountAction
tooltip: qsTr("Add new Account")
onTriggered:
{
var account = stateListModel.newAccount("1000000", QEther.Ether);
stateAccounts.push(account);
accountsModel.append(account);
}
}
} }
Ether {
id: balanceField MessageDialog
edit: true {
displayFormattedValue: true id: alertAlreadyUsed
text: qsTr("This account is in use. You cannot remove it. The first account is used to deploy config contract and cannot be removed.")
icon: StandardIcon.Warning
standardButtons: StandardButton.Ok
}
TableView
{
id: accountsView
Layout.fillWidth: true Layout.fillWidth: true
model: accountsModel
headerVisible: false
TableViewColumn {
role: "name"
title: qsTr("Name")
width: 150
delegate: Item {
RowLayout
{
height: 25
width: parent.width
Button
{
iconSource: "qrc:/qml/img/delete_sign.png"
action: deleteAccountAction
}
Action {
id: deleteAccountAction
tooltip: qsTr("Delete Account")
onTriggered:
{
if (transactionsModel.isUsed(stateAccounts[styleData.row].secret))
alertAlreadyUsed.open();
else
{
stateAccounts.splice(styleData.row, 1);
accountsModel.remove(styleData.row);
}
}
}
DefaultTextField {
anchors.verticalCenter: parent.verticalCenter
onTextChanged: {
if (styleData.row > -1)
stateAccounts[styleData.row].name = text;
}
text: {
return styleData.value
}
}
}
}
}
TableViewColumn {
role: "balance"
title: qsTr("Balance")
width: 200
delegate: Item {
Ether {
id: balanceField
edit: true
displayFormattedValue: false
value: styleData.value
}
}
}
rowDelegate:
Rectangle {
color: styleData.alternate ? "transparent" : "#f0f0f0"
height: 30;
}
} }
} }
@ -196,10 +303,21 @@ Window {
} }
} }
ListModel {
id: accountsModel
function removeAccount(_i)
{
accountsModel.remove(_i);
stateAccounts.splice(_i, 1);
}
}
ListModel { ListModel {
id: transactionsModel id: transactionsModel
function editTransaction(index) { function editTransaction(index) {
transactionDialog.stateAccounts = stateAccounts;
transactionDialog.open(index, transactionsModel.get(index)); transactionDialog.open(index, transactionsModel.get(index));
} }
@ -209,6 +327,7 @@ Window {
// https://bugreports.qt-project.org/browse/QTBUG-41327 // https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handler would just edit the item that was just created, no harm done // Second call to signal handler would just edit the item that was just created, no harm done
var item = TransactionHelper.defaultTransaction(); var item = TransactionHelper.defaultTransaction();
transactionDialog.stateAccounts = stateAccounts;
transactionDialog.open(transactionsModel.count, item); transactionDialog.open(transactionsModel.count, item);
} }
@ -216,6 +335,16 @@ Window {
stateTransactions.splice(index, 1); stateTransactions.splice(index, 1);
transactionsModel.remove(index); transactionsModel.remove(index);
} }
function isUsed(secret)
{
for (var i in stateTransactions)
{
if (stateTransactions[i].sender === secret)
return true;
}
return false;
}
} }
Component { Component {

59
mix/qml/StateListModel.qml

@ -11,25 +11,39 @@ Item {
property alias model: stateListModel property alias model: stateListModel
property var stateList: [] property var stateList: []
property string defaultAccount: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" //support for old project
function fromPlainStateItem(s) { function fromPlainStateItem(s) {
if (!s.accounts)
s.accounts = [stateListModel.newAccount("1000000", QEther.Ether, defaultAccount)]; //support for old project
return { return {
title: s.title, title: s.title,
balance: QEtherHelper.createEther(s.balance.value, s.balance.unit), transactions: s.transactions.map(fromPlainTransactionItem),
transactions: s.transactions.map(fromPlainTransactionItem) accounts: s.accounts.map(fromPlainAccountItem)
};
}
function fromPlainAccountItem(t)
{
return {
name: t.name,
secret: t.secret,
balance: QEtherHelper.createEther(t.balance.value, t.balance.unit)
}; };
} }
function fromPlainTransactionItem(t) { function fromPlainTransactionItem(t) {
if (!t.sender)
t.sender = defaultAccount; //support for old project
var r = { var r = {
contractId: t.contractId, contractId: t.contractId,
functionId: t.functionId, functionId: t.functionId,
url: t.url, url: t.url,
value: QEtherHelper.createEther(t.value.value, t.value.unit), value: QEtherHelper.createEther(t.value.value, t.value.unit),
gas: QEtherHelper.createBigInt(t.gas.value), //t.gas,//QEtherHelper.createEther(t.gas.value, t.gas.unit), gas: QEtherHelper.createBigInt(t.gas.value),
gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit),
stdContract: t.stdContract, stdContract: t.stdContract,
parameters: {} parameters: {},
sender: t.sender
}; };
var qType = []; var qType = [];
for (var key in t.parameters) for (var key in t.parameters)
@ -65,8 +79,8 @@ Item {
function toPlainStateItem(s) { function toPlainStateItem(s) {
return { return {
title: s.title, title: s.title,
balance: { value: s.balance.value, unit: s.balance.unit }, transactions: s.transactions.map(toPlainTransactionItem),
transactions: s.transactions.map(toPlainTransactionItem) accounts: s.accounts.map(toPlainAccountItem)
}; };
} }
@ -80,6 +94,18 @@ Item {
return ''; return '';
} }
function toPlainAccountItem(t)
{
return {
name: t.name,
secret: t.secret,
balance: {
value: t.balance.value,
unit: t.balance.unit
}
};
}
function toPlainTransactionItem(t) { function toPlainTransactionItem(t) {
var r = { var r = {
contractId: t.contractId, contractId: t.contractId,
@ -152,7 +178,6 @@ Item {
ListModel { ListModel {
id: stateListModel id: stateListModel
property int defaultStateIndex: 0 property int defaultStateIndex: 0
signal defaultStateChanged; signal defaultStateChanged;
signal stateListModelReady; signal stateListModelReady;
@ -167,15 +192,23 @@ Item {
}; };
} }
function newAccount(_balance, _unit, _secret)
{
if (!_secret)
_secret = clientModel.newAddress();
var name = qsTr("Account") + "-" + _secret.substring(0, 4);
return { name: name, secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) };
}
function createDefaultState() { function createDefaultState() {
//var ether = QEtherHelper.createEther("100000000000000000000000000", QEther.Wei);
var ether = QEtherHelper.createEther("1000000", QEther.Ether);
var item = { var item = {
title: "", title: "",
balance: ether, transactions: [],
transactions: [] accounts: []
}; };
item.accounts.push(newAccount("1000000", QEther.Ether, defaultAccount));
//add all stdc contracts //add all stdc contracts
for (var i = 0; i < contractLibrary.model.count; i++) { for (var i = 0; i < contractLibrary.model.count; i++) {
var contractTransaction = defaultTransactionItem(); var contractTransaction = defaultTransactionItem();
@ -184,6 +217,7 @@ Item {
contractTransaction.contractId = contractItem.name; contractTransaction.contractId = contractItem.name;
contractTransaction.functionId = contractItem.name; contractTransaction.functionId = contractItem.name;
contractTransaction.stdContract = true; contractTransaction.stdContract = true;
contractTransaction.sender = item.accounts[0].secret; // default account is used to deploy std contract.
item.transactions.push(contractTransaction); item.transactions.push(contractTransaction);
}; };
@ -192,6 +226,7 @@ Item {
var ctorTr = defaultTransactionItem(); var ctorTr = defaultTransactionItem();
ctorTr.functionId = c; ctorTr.functionId = c;
ctorTr.contractId = c; ctorTr.contractId = c;
ctorTr.sender = item.accounts[0].secret;
item.transactions.push(ctorTr); item.transactions.push(ctorTr);
} }
return item; return item;

2
mix/qml/StatusPane.qml

@ -164,8 +164,6 @@ Rectangle {
RowLayout RowLayout
{ {
anchors.fill: parent anchors.fill: parent
anchors.top: parent.top
anchors.right: parent.right
Rectangle Rectangle
{ {
color: "transparent" color: "transparent"

33
mix/qml/TransactionDialog.qml

@ -25,6 +25,7 @@ Window {
property var itemParams; property var itemParams;
property bool useTransactionDefaultValue: false property bool useTransactionDefaultValue: false
property var qType; property var qType;
property alias stateAccounts: senderComboBox.model
signal accepted; signal accepted;
@ -44,6 +45,8 @@ Window {
rowFunction.visible = true; rowFunction.visible = true;
itemParams = item.parameters !== undefined ? item.parameters : {}; itemParams = item.parameters !== undefined ? item.parameters : {};
if (item.sender)
senderComboBox.select(item.sender);
contractsModel.clear(); contractsModel.clear();
var contractIndex = -1; var contractIndex = -1;
@ -190,6 +193,7 @@ Window {
item.functionId = transactionDialog.functionId; item.functionId = transactionDialog.functionId;
} }
item.sender = senderComboBox.model[senderComboBox.currentIndex].secret;
var orderedQType = []; var orderedQType = [];
for (var p = 0; p < transactionDialog.transactionParams.count; p++) { for (var p = 0; p < transactionDialog.transactionParams.count; p++) {
var parameter = transactionDialog.transactionParams.get(p); var parameter = transactionDialog.transactionParams.get(p);
@ -210,6 +214,35 @@ Window {
id: dialogContent id: dialogContent
anchors.top: parent.top anchors.top: parent.top
spacing: 10 spacing: 10
RowLayout
{
id: rowSender
Layout.fillWidth: true
height: 150
DefaultLabel {
Layout.preferredWidth: 75
text: qsTr("Sender")
}
ComboBox {
function select(secret)
{
for (var i in model)
if (model[i].secret === secret)
{
currentIndex = i;
break;
}
}
id: senderComboBox
Layout.preferredWidth: 350
currentIndex: 0
textRole: "name"
editable: false
}
}
RowLayout RowLayout
{ {
id: rowContract id: rowContract

6
mix/qml/TransactionLog.qml

@ -38,6 +38,12 @@ Item {
if (codeModel.hasContract && !clientModel.running) if (codeModel.hasContract && !clientModel.running)
projectModel.stateListModel.debugDefaultState(); projectModel.stateListModel.debugDefaultState();
} }
onProjectClosed:
{
fullModel.clear();
transactionModel.clear();
callModel.clear();
}
} }
ComboBox { ComboBox {

1
neth/CMakeLists.txt

@ -5,6 +5,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${LEVELDB_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE neth) set(EXECUTABLE neth)

2
neth/main.cpp

@ -25,8 +25,10 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <signal.h> #include <signal.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp> #include <boost/algorithm/string/trim_all.hpp>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethereum/All.h> #include <libethereum/All.h>

14
secp256k1/CMakeLists.txt

@ -21,6 +21,18 @@ if (APPLE OR UNIX)
endif() endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM")
target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES})
elseif (CMAKE_COMPILER_IS_MINGW)
include_directories(${Boost_INCLUDE_DIRS})
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm)
else()
add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -W -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM")
target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES})
else() else()
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
@ -36,5 +48,5 @@ else()
endif() endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

19
test/SolidityEndToEndTest.cpp

@ -1619,9 +1619,11 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
function sendAmount(uint amount) returns (uint256 bal) { function sendAmount(uint amount) returns (uint256 bal) {
return h.getBalance.value(amount)(); return h.getBalance.value(amount)();
} }
function outOfGas() returns (bool flagBefore, bool flagAfter, uint myBal) { function outOfGas() returns (bool ret) {
flagBefore = h.getFlag(); h.setFlag.gas(2)(); // should fail due to OOG
h.setFlag.gas(2)(); // should fail due to OOG, return value can be garbage return true;
}
function checkState() returns (bool flagAfter, uint myBal) {
flagAfter = h.getFlag(); flagAfter = h.getFlag();
myBal = this.balance; myBal = this.balance;
} }
@ -1630,7 +1632,8 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic)
compileAndRun(sourceCode, 20); compileAndRun(sourceCode, 20);
BOOST_REQUIRE(callContractFunction("sendAmount(uint256)", 5) == encodeArgs(5)); BOOST_REQUIRE(callContractFunction("sendAmount(uint256)", 5) == encodeArgs(5));
// call to helper should not succeed but amount should be transferred anyway // call to helper should not succeed but amount should be transferred anyway
BOOST_REQUIRE(callContractFunction("outOfGas()", 5) == encodeArgs(false, false, 20 - 5)); BOOST_REQUIRE(callContractFunction("outOfGas()", 5) == bytes());
BOOST_REQUIRE(callContractFunction("checkState()", 5) == encodeArgs(false, 20 - 5));
} }
BOOST_AUTO_TEST_CASE(value_complex) BOOST_AUTO_TEST_CASE(value_complex)
@ -2504,11 +2507,11 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete)
compileAndRun(sourceCode); compileAndRun(sourceCode);
string data = "123456789012345678901234567890123"; string data = "123456789012345678901234567890123";
BOOST_CHECK(m_state.storage(m_contractAddress).empty()); BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true)); BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true));
BOOST_CHECK(!m_state.storage(m_contractAddress).empty()); BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true)); BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true));
BOOST_CHECK(m_state.storage(m_contractAddress).empty()); BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true)); BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true));
BOOST_CHECK(!m_state.storage(m_contractAddress).empty()); BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("del()") == encodeArgs(true)); BOOST_CHECK(callContractFunction("del()") == encodeArgs(true));
BOOST_CHECK(m_state.storage(m_contractAddress).empty()); BOOST_CHECK(m_state.storage(m_contractAddress).empty());
@ -2661,8 +2664,8 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments)
bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13); bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13);
string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3)); string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3));
bytes calldata = encodeArgs( bytes calldata = encodeArgs(
u256(innercalldata1.length()), u256(innercalldata2.length()), 12, u256(innercalldata1.length()), u256(innercalldata2.length()), 13,
12, innercalldata1, innercalldata2, 13); innercalldata1, innercalldata2);
BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata)
== encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length())));
} }

4
test/TestHelper.cpp

@ -23,7 +23,9 @@
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
@ -170,7 +172,7 @@ void ImportTest::importTransaction(json_spirit::mObject& _o)
} }
} }
void ImportTest::exportTest(bytes _output, State& _statePost) void ImportTest::exportTest(bytes const& _output, State const& _statePost)
{ {
// export output // export output
m_TestObject["out"] = "0x" + toHex(_output); m_TestObject["out"] = "0x" + toHex(_output);

4
test/TestHelper.h

@ -22,7 +22,9 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libevm/ExtVMFace.h> #include <libevm/ExtVMFace.h>
@ -52,7 +54,7 @@ public:
void importEnv(json_spirit::mObject& _o); void importEnv(json_spirit::mObject& _o);
void importState(json_spirit::mObject& _o, eth::State& _state); void importState(json_spirit::mObject& _o, eth::State& _state);
void importTransaction(json_spirit::mObject& _o); void importTransaction(json_spirit::mObject& _o);
void exportTest(bytes _output, eth::State& _statePost); void exportTest(bytes const& _output, eth::State const& _statePost);
eth::State m_statePre; eth::State m_statePre;
eth::State m_statePost; eth::State m_statePost;

144
test/block.cpp

@ -81,6 +81,76 @@ bytes createBlockRLPFromFields(mObject& _tObj)
return rlpStream.out(); return rlpStream.out();
} }
void overwriteBlockHeader(mObject& _o, BlockInfo _current_BlockHeader)
{
if (_o.count("blockHeader"))
{
if (_o["blockHeader"].get_obj().size() != 14)
{
BlockInfo tmp = _current_BlockHeader;
if (_o["blockHeader"].get_obj().count("parentHash"))
tmp.parentHash = h256(_o["blockHeader"].get_obj()["parentHash"].get_str());
if (_o["blockHeader"].get_obj().count("uncleHash"))
tmp.sha3Uncles = h256(_o["blockHeader"].get_obj()["uncleHash"].get_str());
if (_o["blockHeader"].get_obj().count("coinbase"))
tmp.coinbaseAddress = Address(_o["blockHeader"].get_obj()["coinbase"].get_str());
if (_o["blockHeader"].get_obj().count("stateRoot"))
tmp.stateRoot = h256(_o["blockHeader"].get_obj()["stateRoot"].get_str());
if (_o["blockHeader"].get_obj().count("transactionsTrie"))
tmp.transactionsRoot = h256(_o["blockHeader"].get_obj()["transactionsTrie"].get_str());
if (_o["blockHeader"].get_obj().count("receiptTrie"))
tmp.receiptsRoot = h256(_o["blockHeader"].get_obj()["receiptTrie"].get_str());
if (_o["blockHeader"].get_obj().count("bloom"))
tmp.logBloom = LogBloom(_o["blockHeader"].get_obj()["bloom"].get_str());
if (_o["blockHeader"].get_obj().count("difficulty"))
tmp.difficulty = toInt(_o["blockHeader"].get_obj()["difficulty"]);
if (_o["blockHeader"].get_obj().count("number"))
tmp.number = toInt(_o["blockHeader"].get_obj()["number"]);
if (_o["blockHeader"].get_obj().count("gasLimit"))
tmp.gasLimit = toInt(_o["blockHeader"].get_obj()["gasLimit"]);
if (_o["blockHeader"].get_obj().count("gasUsed"))
tmp.gasUsed = toInt(_o["blockHeader"].get_obj()["gasUsed"]);
if (_o["blockHeader"].get_obj().count("timestamp"))
tmp.timestamp = toInt(_o["blockHeader"].get_obj()["timestamp"]);
if (_o["blockHeader"].get_obj().count("extraData"))
tmp.extraData = importByteArray(_o["blockHeader"].get_obj()["extraData"].get_str());
// find new valid nonce
if (tmp != _current_BlockHeader)
{
_current_BlockHeader = tmp;
cout << "new header!\n";
ProofOfWork pow;
MineInfo ret;
while (!ProofOfWork::verify(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.nonce, _current_BlockHeader.difficulty))
tie(ret, _current_BlockHeader.nonce) = pow.mine(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.difficulty, 10000, true, true);
}
}
else
{
// take the blockheader as is
const bytes c_blockRLP = createBlockRLPFromFields(_o["blockHeader"].get_obj());
const RLP c_bRLP(c_blockRLP);
_current_BlockHeader.populateFromHeader(c_bRLP, false);
}
}
}
void doBlockTests(json_spirit::mValue& _v, bool _fillin) void doBlockTests(json_spirit::mValue& _v, bool _fillin)
{ {
for (auto& i: _v.get_obj()) for (auto& i: _v.get_obj())
@ -214,76 +284,9 @@ void doBlockTests(json_spirit::mValue& _v, bool _fillin)
BlockInfo current_BlockHeader = state.info(); BlockInfo current_BlockHeader = state.info();
// overwrite blockheader with (possible wrong) data from "blockheader" in filler; // overwrite blockheader with (possible wrong) data from "blockheader" in filler;
overwriteBlockHeader(o, current_BlockHeader);
if (o.count("blockHeader"))
{
if (o["blockHeader"].get_obj().size() != 14)
{
BlockInfo tmp = current_BlockHeader;
if (o["blockHeader"].get_obj().count("parentHash"))
tmp.parentHash = h256(o["blockHeader"].get_obj()["parentHash"].get_str());
if (o["blockHeader"].get_obj().count("uncleHash"))
tmp.sha3Uncles = h256(o["blockHeader"].get_obj()["uncleHash"].get_str());
if (o["blockHeader"].get_obj().count("coinbase"))
tmp.coinbaseAddress = Address(o["blockHeader"].get_obj()["coinbase"].get_str());
if (o["blockHeader"].get_obj().count("stateRoot"))
tmp.stateRoot = h256(o["blockHeader"].get_obj()["stateRoot"].get_str());
if (o["blockHeader"].get_obj().count("transactionsTrie"))
tmp.transactionsRoot = h256(o["blockHeader"].get_obj()["transactionsTrie"].get_str());
if (o["blockHeader"].get_obj().count("receiptTrie"))
tmp.receiptsRoot = h256(o["blockHeader"].get_obj()["receiptTrie"].get_str());
if (o["blockHeader"].get_obj().count("bloom"))
tmp.logBloom = LogBloom(o["blockHeader"].get_obj()["bloom"].get_str());
if (o["blockHeader"].get_obj().count("difficulty"))
tmp.difficulty = toInt(o["blockHeader"].get_obj()["difficulty"]);
if (o["blockHeader"].get_obj().count("number"))
tmp.number = toInt(o["blockHeader"].get_obj()["number"]);
if (o["blockHeader"].get_obj().count("gasLimit"))
tmp.gasLimit = toInt(o["blockHeader"].get_obj()["gasLimit"]);
if (o["blockHeader"].get_obj().count("gasUsed"))
tmp.gasUsed = toInt(o["blockHeader"].get_obj()["gasUsed"]);
if (o["blockHeader"].get_obj().count("timestamp"))
tmp.timestamp = toInt(o["blockHeader"].get_obj()["timestamp"]);
if (o["blockHeader"].get_obj().count("extraData"))
tmp.extraData = importByteArray(o["blockHeader"].get_obj()["extraData"].get_str());
// find new valid nonce
if (tmp != current_BlockHeader)
{
current_BlockHeader = tmp;
cout << "new header!\n";
ProofOfWork pow;
MineInfo ret;
while (!ProofOfWork::verify(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.nonce, current_BlockHeader.difficulty))
tie(ret, current_BlockHeader.nonce) = pow.mine(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.difficulty, 10000, true, true);
}
}
else
{
// take the blockheader as is
const bytes c_blockRLP = createBlockRLPFromFields(o["blockHeader"].get_obj());
const RLP c_bRLP(c_blockRLP);
current_BlockHeader.populateFromHeader(c_bRLP, false);
}
}
// write block header // write block header
mObject oBlockHeader; mObject oBlockHeader;
oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash); oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash);
oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles); oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles);
@ -423,7 +426,6 @@ void doBlockTests(json_spirit::mValue& _v, bool _fillin)
BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!");
//Check transaction list //Check transaction list
Transactions txsFromField; Transactions txsFromField;
for (auto const& txObj: o["transactions"].get_array()) for (auto const& txObj: o["transactions"].get_array())
@ -511,9 +513,9 @@ BOOST_AUTO_TEST_CASE(blForkBlocks)
dev::test::executeTests("blForkBlocks", "/BlockTests", dev::test::doBlockTests); dev::test::executeTests("blForkBlocks", "/BlockTests", dev::test::doBlockTests);
} }
BOOST_AUTO_TEST_CASE(userDefinedFileBl) BOOST_AUTO_TEST_CASE(userDefinedFile)
{ {
dev::test::userDefinedTest("--bltest", dev::test::doBlockTests); dev::test::userDefinedTest("--singletest", dev::test::doBlockTests);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

2
test/createRandomTest.cpp

@ -23,8 +23,10 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
#include <boost/random.hpp> #include <boost/random.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
#include <json_spirit/json_spirit.h> #include <json_spirit/json_spirit.h>
#include <json_spirit/json_spirit_reader_template.h> #include <json_spirit/json_spirit_reader_template.h>

1
test/fork.cpp

@ -22,6 +22,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>

4
test/genesis.cpp

@ -22,10 +22,12 @@
#include <fstream> #include <fstream>
#include <random> #include <random>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

4
test/hexPrefix.cpp

@ -21,11 +21,13 @@
*/ */
#include <fstream> #include <fstream>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieCommon.h> #include <libdevcrypto/TrieCommon.h>
#include <boost/test/unit_test.hpp>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

1
test/net.cpp

@ -20,6 +20,7 @@
*/ */
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libp2p/UDP.h> #include <libp2p/UDP.h>

4
test/rlp.cpp

@ -22,11 +22,13 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <boost/test/unit_test.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <boost/test/unit_test.hpp>
#include <algorithm> #include <algorithm>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include "TestHelper.h" #include "TestHelper.h"

3
test/state.cpp

@ -22,6 +22,7 @@
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
@ -241,7 +242,7 @@ BOOST_AUTO_TEST_CASE(stCreateTest)
BOOST_AUTO_TEST_CASE(userDefinedFileState) BOOST_AUTO_TEST_CASE(userDefinedFileState)
{ {
dev::test::userDefinedTest("--statetest", dev::test::doStateTests); dev::test::userDefinedTest("--singletest", dev::test::doStateTests);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save