Browse Source

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

cl-refactor
Paweł Bylica 10 years ago
parent
commit
0a6111e0d4
  1. 19
      alethzero/MainWin.cpp
  2. 4
      alethzero/OurWebThreeStubServer.h
  3. 27
      build.py
  4. 13
      cmake/EthExecutableHelper.cmake
  5. 3
      libdevcore/CMakeLists.txt
  6. 2
      libdevcore/Common.cpp
  7. 2
      libdevcrypto/TrieDB.h
  8. 51
      libethcore/CommonJS.cpp
  9. 40
      libethcore/CommonJS.h
  10. 2
      libethereum/All.h
  11. 62
      libethereum/BlockChain.cpp
  12. 18
      libethereum/BlockChain.h
  13. 86
      libethereum/CanonBlockChain.cpp
  14. 76
      libethereum/CanonBlockChain.h
  15. 7
      libethereum/Client.cpp
  16. 6
      libethereum/Client.h
  17. 7
      libethereum/LogFilter.cpp
  18. 16
      libethereum/LogFilter.h
  19. 13
      libethereum/State.cpp
  20. 4
      libethereum/State.h
  21. 2
      libjsqrc/ethereumjs/bower.json
  22. 377
      libjsqrc/ethereumjs/dist/ethereum.js
  23. 22
      libjsqrc/ethereumjs/dist/ethereum.js.map
  24. 2
      libjsqrc/ethereumjs/dist/ethereum.min.js
  25. 66
      libjsqrc/ethereumjs/example/event_inc.html
  26. 23
      libjsqrc/ethereumjs/lib/const.js
  27. 11
      libjsqrc/ethereumjs/lib/contract.js
  28. 72
      libjsqrc/ethereumjs/lib/event.js
  29. 7
      libjsqrc/ethereumjs/lib/filter.js
  30. 32
      libjsqrc/ethereumjs/lib/httpsync.js
  31. 65
      libjsqrc/ethereumjs/lib/jsonrpc.js
  32. 45
      libjsqrc/ethereumjs/lib/providermanager.js
  33. 3
      libjsqrc/ethereumjs/lib/qtsync.js
  34. 33
      libjsqrc/ethereumjs/lib/utils.js
  35. 62
      libjsqrc/ethereumjs/lib/web3.js
  36. 2
      libjsqrc/ethereumjs/package.json
  37. 438
      libjsqrc/ethereumjs/test/abi.inputParser.js
  38. 461
      libjsqrc/ethereumjs/test/abi.outputParser.js
  39. 2
      libjsqrc/ethereumjs/test/db.methods.js
  40. 2
      libjsqrc/ethereumjs/test/eth.methods.js
  41. 125
      libjsqrc/ethereumjs/test/event.inputParser.js
  42. 124
      libjsqrc/ethereumjs/test/event.js
  43. 81
      libjsqrc/ethereumjs/test/event.outputParser.js
  44. 143
      libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js
  45. 47
      libjsqrc/ethereumjs/test/jsonrpc.toBatchPayload.js
  46. 40
      libjsqrc/ethereumjs/test/jsonrpc.toPayload.js
  47. 2
      libjsqrc/ethereumjs/test/shh.methods.js
  48. 0
      libjsqrc/ethereumjs/test/test.utils.js
  49. 42
      libjsqrc/ethereumjs/test/utils.extractDisplayName.js
  50. 55
      libjsqrc/ethereumjs/test/utils.extractTypeName.js
  51. 2
      libjsqrc/ethereumjs/test/web3.methods.js
  52. 12
      libjsqrc/natspec.js
  53. 2
      libp2p/Capability.cpp
  54. 6
      libp2p/Host.cpp
  55. 17
      libp2p/Session.cpp
  56. 13
      libqwebthree/QWebThree.cpp
  57. 92
      libserpent/compiler.cpp
  58. 5
      libserpent/compiler.h
  59. 7
      libserpent/util.cpp
  60. 45
      libsolidity/AST.cpp
  61. 41
      libsolidity/AST.h
  62. 4
      libsolidity/Compiler.cpp
  63. 72
      libsolidity/ExpressionCompiler.cpp
  64. 4
      libsolidity/ExpressionCompiler.h
  65. 89
      libsolidity/Parser.cpp
  66. 7
      libsolidity/Parser.h
  67. 2
      libsolidity/Token.h
  68. 23
      libsolidity/Types.cpp
  69. 7
      libsolidity/grammar.txt
  70. 7
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  71. 4
      libweb3jsonrpc/WebThreeStubServerBase.h
  72. 45
      macdeployfix.sh
  73. 14
      mix/AppContext.cpp
  74. 4
      mix/AppContext.h
  75. 41
      mix/ClientModel.cpp
  76. 5
      mix/ClientModel.h
  77. 2
      mix/ContractCallDataEncoder.cpp
  78. 2
      mix/DebuggingStateWrapper.cpp
  79. 222
      mix/MixClient.cpp
  80. 30
      mix/MixClient.h
  81. 2
      mix/QBigInt.cpp
  82. 2
      mix/QBigInt.h
  83. 2
      mix/QVariableDefinition.cpp
  84. 3
      mix/qml/MainContent.qml
  85. 15
      mix/qml/WebCodeEditor.qml
  86. 2
      mix/qml/html/cm/codemirror.js
  87. 20
      mix/qml/html/codeeditor.js
  88. 1
      mix/qml/main.qml
  89. 5
      pullSerpent.sh
  90. 5
      sc/cmdline.cpp
  91. 55
      test/SolidityEndToEndTest.cpp
  92. 134
      test/SolidityNameAndTypeResolution.cpp
  93. 49
      test/SolidityParser.cpp
  94. 5
      test/commonjs.cpp
  95. 2
      test/fork.cpp
  96. 8
      test/genesis.cpp
  97. 2
      test/jsonrpc.cpp
  98. 2
      test/state.cpp
  99. 4
      test/stateOriginal.cpp
  100. 2
      test/txTest.cpp

19
alethzero/MainWin.cpp

@ -33,7 +33,7 @@
#include <libserpent/funcs.h> #include <libserpent/funcs.h>
#include <libserpent/util.h> #include <libserpent/util.h>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <liblll/CodeFragment.h> #include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
@ -41,7 +41,7 @@
#include <libsolidity/SourceReferenceFormatter.h> #include <libsolidity/SourceReferenceFormatter.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/Utility.h> #include <libethereum/Utility.h>
@ -136,9 +136,9 @@ Main::Main(QWidget *parent) :
#endif #endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303")); m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
cerr << "State root: " << BlockChain::genesis().stateRoot << endl; cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl;
auto block = BlockChain::createGenesisBlock(); auto block = CanonBlockChain::createGenesisBlock();
cerr << "Block Hash: " << BlockChain::genesis().hash << endl; cerr << "Block Hash: " << CanonBlockChain::genesis().hash << endl;
cerr << "Block RLP: " << RLP(block) << endl; cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << endl; cerr << "Block Hex: " << toHex(block) << endl;
cerr << "Network protocol version: " << c_protocolVersion << endl; cerr << "Network protocol version: " << c_protocolVersion << endl;
@ -1047,7 +1047,7 @@ void Main::refreshBlockCount()
ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet"));
} }
static bool blockMatch(string const& _f, BlockDetails const& _b, h256 _h, BlockChain const& _bc) static bool blockMatch(string const& _f, BlockDetails const& _b, h256 _h, CanonBlockChain const& _bc)
{ {
try try
{ {
@ -1189,7 +1189,10 @@ void Main::timerEvent(QTimerEvent*)
{ {
auto ls = ethereum()->checkWatch(i.first); auto ls = ethereum()->checkWatch(i.first);
if (ls.size()) if (ls.size())
{
cnote << "FIRING WATCH" << i.first << ls.size();
i.second(ls); i.second(ls);
}
} }
} }
@ -1202,7 +1205,7 @@ string Main::renderDiff(StateDiff const& _d) const
{ {
s << "<hr/>"; s << "<hr/>";
AccountDiff const& ad = i.second; AccountDiff ad = i.second;
s << "<code style=\"white-space: pre; font-weight: bold\">" << lead(ad.changeType()) << " </code>" << " <b>" << render(i.first).toStdString() << "</b>"; s << "<code style=\"white-space: pre; font-weight: bold\">" << lead(ad.changeType()) << " </code>" << " <b>" << render(i.first).toStdString() << "</b>";
if (!ad.exist.to()) if (!ad.exist.to())
continue; continue;
@ -1210,7 +1213,7 @@ string Main::renderDiff(StateDiff const& _d) const
if (ad.balance) if (ad.balance)
{ {
s << "<br/>" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]"; s << "<br/>" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]";
auto d = (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())); bigint d = (dev::bigint)ad.balance.to() - (dev::bigint)ad.balance.from();
s << " <b>" << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << "</b>"; s << " <b>" << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << "</b>";
} }
if (ad.nonce) if (ad.nonce)

4
alethzero/OurWebThreeStubServer.h

@ -20,7 +20,7 @@
*/ */
#include <QtCore/QObject> #include <QtCore/QObject>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>
@ -35,7 +35,7 @@ public:
std::vector<dev::KeyPair> const& _accounts, Main* main); std::vector<dev::KeyPair> const& _accounts, Main* main);
virtual std::string shh_newIdentity() override; virtual std::string shh_newIdentity() override;
virtual bool authenticate(dev::TransactionSkeleton const& _t); virtual bool authenticate(dev::eth::TransactionSkeleton const& _t);
signals: signals:
void onNewId(QString _s); void onNewId(QString _s);

27
build.py

@ -1,27 +0,0 @@
#!/usr/bin/python
# cpp-ethereum build script
# to be used from CI server, or to build locally
# uses python instead of bash script for better cross-platform support
# TODO Initial version. Needs much more improvements
import argparse
import os
import subprocess
def build_dependencies():
if os.path.exists("extdep"):
os.chdir("extdep")
if not os.path.exists("build"):
os.makedirs("build")
os.chdir("build")
subprocess.check_call(["cmake", ".."])
subprocess.check_call("make")
parser = argparse.ArgumentParser()
parser.add_argument("cmd", help="what to build")
args = parser.parse_args()
if args.cmd == "dep":
build_dependencies()

13
cmake/EthExecutableHelper.cmake

@ -71,8 +71,9 @@ macro(eth_install_executable EXECUTABLE)
if (APPLE) if (APPLE)
# First have qt5 install plugins and frameworks # First have qt5 install plugins and frameworks
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app ${eth_qml_dir} COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir}
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents
) )
# This tool and next will inspect linked libraries in order to determine which dependencies are required # This tool and next will inspect linked libraries in order to determine which dependencies are required
@ -82,19 +83,11 @@ macro(eth_install_executable EXECUTABLE)
set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app")
endif () endif ()
# TODO check, how fixup_bundle works and if it is required
install(CODE " install(CODE "
include(BundleUtilities) include(BundleUtilities)
set(BU_CHMOD_BUNDLE_ITEMS 1) set(BU_CHMOD_BUNDLE_ITEMS 1)
fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\") verify_app(\"${APP_BUNDLE_PATH}\")
" COMPONENT RUNTIME ) " COMPONENT RUNTIME )
# Cleanup duplicate libs from macdeployqt
install(CODE "
file(GLOB LINGER_RM \"${APP_BUNDLE_PATH}/Contents/Frameworks/*.dylib\")
if (LINGER_RM)
file(REMOVE \${LINGER_RM})
endif ()
")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# copy all dlls to executable directory # copy all dlls to executable directory

3
libdevcore/CMakeLists.txt

@ -26,9 +26,8 @@ else()
endif() endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES}) #target_link_libraries(${EXECUTABLE} ${Boost_DATE_TIME_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_CHRONO_LIBRARIES})
if (APPLE) if (APPLE)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev namespace dev
{ {
char const* Version = "0.8.0"; char const* Version = "0.8.1";
} }

2
libdevcrypto/TrieDB.h

@ -49,7 +49,7 @@ extern const h256 EmptyTrie;
/** /**
* @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree.
* This version uses an database backend. * This version uses a database backend.
* Usage: * Usage:
* @code * @code
* GenericTrieDB<MyDB> t(&myDB); * GenericTrieDB<MyDB> t(&myDB);

51
libdevcore/CommonJS.cpp → libethcore/CommonJS.cpp

@ -72,6 +72,31 @@ bytes unpadLeft(bytes _b)
return _b; return _b;
} }
std::string fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
std::string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return "";
if (l != std::string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == std::string::npos || (_inc && p == 31)))
return "";
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return "";
return s;
}
return "";
}
std::string prettyU256(u256 _n) std::string prettyU256(u256 _n)
{ {
unsigned inc = 0; unsigned inc = 0;
@ -98,31 +123,6 @@ std::string prettyU256(u256 _n)
return s.str(); return s.str();
} }
std::string fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
std::string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return "";
if (l != std::string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == std::string::npos || (_inc && p == 31)))
return "";
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return "";
return s;
}
return "";
}
Address fromString(std::string const& _sn) Address fromString(std::string const& _sn)
{ {
if (_sn.size() == 40) if (_sn.size() == 40)
@ -132,3 +132,4 @@ Address fromString(std::string const& _sn)
} }
} }

40
libdevcore/CommonJS.h → libethcore/CommonJS.h

@ -24,9 +24,11 @@
#pragma once #pragma once
#include <string> #include <string>
#include <libethereum/Interface.h> #include <libdevcore/Common.h>
#include "Common.h" #include <libdevcore/FixedHash.h>
#include "CommonData.h" #include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include "CommonEth.h"
namespace dev namespace dev
{ {
@ -94,16 +96,8 @@ template <unsigned N> boost::multiprecision::number<boost::multiprecision::cpp_i
return 0; // FAIL return 0; // FAIL
} }
inline Address jsToAddress(std::string const& _s) { return jsToFixed<sizeof(dev::Address)>(_s); }
inline Public jsToPublic(std::string const& _s) { return jsToFixed<sizeof(dev::Public)>(_s); }
inline Secret jsToSecret(std::string const& _s) { return jsToFixed<sizeof(dev::Secret)>(_s); }
inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); } inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); }
inline std::string jsToBinary(std::string const& _s)
{
return dev::toString(unpadded(jsToBytes(_s)));
}
inline std::string jsToDecimal(std::string const& _s) inline std::string jsToDecimal(std::string const& _s)
{ {
return dev::toString(jsToU256(_s)); return dev::toString(jsToU256(_s));
@ -125,6 +119,29 @@ inline double jsFromFixed(std::string const& _s)
return (double)jsToU256(_s) / (double)(dev::u256(1) << 128); return (double)jsToU256(_s) / (double)(dev::u256(1) << 128);
} }
}
// devcrypto
#include <libdevcrypto/Common.h>
namespace dev
{
inline Public jsToPublic(std::string const& _s) { return jsToFixed<sizeof(dev::Public)>(_s); }
inline Secret jsToSecret(std::string const& _s) { return jsToFixed<sizeof(dev::Secret)>(_s); }
}
// ethcore
namespace dev
{
namespace eth
{
inline Address jsToAddress(std::string const& _s) { return jsToFixed<sizeof(dev::Address)>(_s); }
struct TransactionSkeleton struct TransactionSkeleton
{ {
Address from; Address from;
@ -136,3 +153,4 @@ struct TransactionSkeleton
}; };
} }
}

2
libethereum/All.h

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Account.h" #include "Account.h"
#include "BlockChain.h" #include "CanonBlockChain.h"
#include "Client.h" #include "Client.h"
#include "Defaults.h" #include "Defaults.h"
#include "Executive.h" #include "Executive.h"

62
libethereum/BlockChain.cpp

@ -53,30 +53,6 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
return _out; return _out;
} }
std::map<Address, Account> const& dev::eth::genesisState()
{
static std::map<Address, Account> s_ret;
if (s_ret.empty())
{
// Initialise.
for (auto i: vector<string>({
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6",
"e6716f9544a56c530d868e4bfbacb172315bdead",
"b9c015918bdaba24b4ff057a92a3873d6eb201be",
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
"2ef47100e0787b915105fd5e3f4ff6752079d5cb",
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
"6c386a4b26f73c802f34673f7248bb118f97424a",
"e4157b34ea9615cfbde6b4fda419828124b70c78"
}))
s_ret[Address(fromHex(i))] = Account(u256(1) << 200, Account::NormalCreation);
}
return s_ret;
}
std::unique_ptr<BlockInfo> BlockChain::s_genesis;
boost::shared_mutex BlockChain::x_genesis;
ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub) ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)
{ {
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT #if ALL_COMPILERS_ARE_CPP11_COMPLIANT
@ -91,31 +67,11 @@ ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)
#endif #endif
} }
bytes BlockChain::createGenesisBlock() BlockChain::BlockChain(bytes const& _genesisBlock, std::string _path, bool _killExisting)
{
RLPStream block(3);
h256 stateRoot;
{
MemoryDB db;
TrieDB<Address, MemoryDB> state(&db);
state.init();
dev::eth::commit(genesisState(), db, state);
stateRoot = state.root();
}
block.appendList(14)
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
}
BlockChain::BlockChain(std::string _path, bool _killExisting)
{ {
// Initialise with the genesis as the last block on the longest chain. // Initialise with the genesis as the last block on the longest chain.
m_genesisHash = BlockChain::genesis().hash; m_genesisBlock = _genesisBlock;
m_genesisBlock = BlockChain::createGenesisBlock(); m_genesisHash = sha3(RLP(m_genesisBlock)[0].data());
open(_path, _killExisting); open(_path, _killExisting);
} }
@ -353,7 +309,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
} }
#endif #endif
// 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;
// This might be the new best block... // This might be the new best block...
@ -377,7 +333,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, bool _post) const h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, bool _post) const
{ {
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged(); // cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
if (!_from || !_to) if (!_from || !_to)
{ {
return h256s(); return h256s();
@ -386,14 +342,14 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
h256s back; h256s back;
unsigned fn = details(_from).number; unsigned fn = details(_from).number;
unsigned tn = details(_to).number; unsigned tn = details(_to).number;
// cdebug << "treeRoute" << fn << "..." << tn; // cdebug << "treeRoute" << fn << "..." << tn;
while (fn > tn) while (fn > tn)
{ {
if (_pre) if (_pre)
ret.push_back(_from); ret.push_back(_from);
_from = details(_from).parent; _from = details(_from).parent;
fn--; fn--;
// cdebug << "from:" << fn << _from.abridged(); // cdebug << "from:" << fn << _from.abridged();
} }
while (fn < tn) while (fn < tn)
{ {
@ -401,7 +357,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to); back.push_back(_to);
_to = details(_to).parent; _to = details(_to).parent;
tn--; tn--;
// cdebug << "to:" << tn << _to.abridged(); // cdebug << "to:" << tn << _to.abridged();
} }
while (_from != _to) while (_from != _to)
{ {
@ -415,7 +371,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to); back.push_back(_to);
fn--; fn--;
tn--; tn--;
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged(); // cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
} }
if (o_common) if (o_common)
*o_common = _from; *o_common = _from;

18
libethereum/BlockChain.h

@ -69,8 +69,7 @@ ldb::Slice toSlice(h256 _h, unsigned _sub = 0);
class BlockChain class BlockChain
{ {
public: public:
BlockChain(bool _killExisting = false): BlockChain(std::string(), _killExisting) {} BlockChain(bytes const& _genesisBlock, std::string _path, bool _killExisting);
BlockChain(std::string _path, bool _killExisting = false);
~BlockChain(); ~BlockChain();
void reopen(std::string _path, bool _killExisting = false) { close(); open(_path, _killExisting); } void reopen(std::string _path, bool _killExisting = false) { close(); open(_path, _killExisting); }
@ -82,7 +81,7 @@ public:
/// Sync the chain with any incoming blocks. All blocks should, if processed in order /// Sync the chain with any incoming blocks. All blocks should, if processed in order
h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max); h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
/// Attempt to import the given block directly into the BlockChain and sync with the state DB. /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain.
h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept; h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept;
@ -131,13 +130,6 @@ public:
/// togther with all their quoted uncles. /// togther with all their quoted uncles.
h256Set allUnclesFrom(h256 _parent) const; h256Set allUnclesFrom(h256 _parent) const;
/// @returns the genesis block header.
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new BlockInfo); s_genesis->populate(&gb); } return *s_genesis; }
/// @returns the genesis block as its RLP-encoded byte array.
/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
static bytes createGenesisBlock();
/** @returns the hash of all blocks between @a _from and @a _to, all blocks are ordered first by a number of /** @returns the hash of all blocks between @a _from and @a _to, all blocks are ordered first by a number of
* blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent. * blocks that are parent-to-child, then two sibling blocks, then a number of blocks that are child-to-parent.
* *
@ -171,7 +163,7 @@ private:
m_extrasDB->Get(m_readOptions, toSlice(_h, N), &s); m_extrasDB->Get(m_readOptions, toSlice(_h, N), &s);
if (s.empty()) if (s.empty())
{ {
// cout << "Not found in DB: " << _h << endl; // cout << "Not found in DB: " << _h << endl;
return _n; return _n;
} }
@ -208,10 +200,6 @@ private:
ldb::WriteOptions m_writeOptions; ldb::WriteOptions m_writeOptions;
friend std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc); friend std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);
/// Static genesis info and its lock.
static boost::shared_mutex x_genesis;
static std::unique_ptr<BlockInfo> s_genesis;
}; };
std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc); std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);

86
libethereum/CanonBlockChain.cpp

@ -0,0 +1,86 @@
/*
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 CanonBlockChain.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "CanonBlockChain.h"
#include <boost/filesystem.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h>
#include <liblll/Compiler.h>
#include "State.h"
#include "Defaults.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
#define ETH_CATCH 1
std::map<Address, Account> const& dev::eth::genesisState()
{
static std::map<Address, Account> s_ret;
if (s_ret.empty())
{
// Initialise.
for (auto i: vector<string>({
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6",
"e6716f9544a56c530d868e4bfbacb172315bdead",
"b9c015918bdaba24b4ff057a92a3873d6eb201be",
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
"2ef47100e0787b915105fd5e3f4ff6752079d5cb",
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
"6c386a4b26f73c802f34673f7248bb118f97424a",
"e4157b34ea9615cfbde6b4fda419828124b70c78"
}))
s_ret[Address(fromHex(i))] = Account(u256(1) << 200, Account::NormalCreation);
}
return s_ret;
}
std::unique_ptr<BlockInfo> CanonBlockChain::s_genesis;
boost::shared_mutex CanonBlockChain::x_genesis;
bytes CanonBlockChain::createGenesisBlock()
{
RLPStream block(3);
h256 stateRoot;
{
MemoryDB db;
TrieDB<Address, MemoryDB> state(&db);
state.init();
dev::eth::commit(genesisState(), db, state);
stateRoot = state.root();
}
block.appendList(14)
<< h256() << EmptyListSHA3 << h160() << stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_genesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << string() << sha3(bytes(1, 42));
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
}
CanonBlockChain::CanonBlockChain(std::string _path, bool _killExisting): BlockChain(CanonBlockChain::createGenesisBlock(), _path, _killExisting)
{
}

76
libethereum/CanonBlockChain.h

@ -0,0 +1,76 @@
/*
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 CanonBlockChain.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <mutex>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
#include <libethcore/CommonEth.h>
#include <libethcore/BlockInfo.h>
#include <libdevcore/Guards.h>
#include "BlockDetails.h"
#include "Account.h"
#include "BlockQueue.h"
#include "BlockChain.h"
namespace ldb = leveldb;
namespace dev
{
namespace eth
{
// TODO: Move all this Genesis stuff into Genesis.h/.cpp
std::map<Address, Account> const& genesisState();
/**
* @brief Implements the blockchain database. All data this gives is disk-backed.
* @threadsafe
* @todo Make not memory hog (should actually act as a cache and deallocate old entries).
*/
class CanonBlockChain: public BlockChain
{
public:
CanonBlockChain(bool _killExisting = false): CanonBlockChain(std::string(), _killExisting) {}
CanonBlockChain(std::string _path, bool _killExisting = false);
~CanonBlockChain() {}
/// @returns the genesis block header.
static BlockInfo const& genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new BlockInfo); s_genesis->populate(&gb); } return *s_genesis; }
/// @returns the genesis block as its RLP-encoded byte array.
/// @note This is slow as it's constructed anew each call. Consider genesis() instead.
static bytes createGenesisBlock();
private:
/// Static genesis info and its lock.
static boost::shared_mutex x_genesis;
static std::unique_ptr<BlockInfo> s_genesis;
};
}
}

7
libethereum/Client.cpp

@ -182,7 +182,7 @@ unsigned Client::installWatch(h256 _h)
Guard l(m_filterLock); Guard l(m_filterLock);
ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0; ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
m_watches[ret] = ClientWatch(_h); m_watches[ret] = ClientWatch(_h);
cwatch << "+++" << ret << _h; cwatch << "+++" << ret << _h.abridged();
} }
auto ch = logs(ret); auto ch = logs(ret);
if (ch.empty()) if (ch.empty())
@ -200,7 +200,10 @@ unsigned Client::installWatch(LogFilter const& _f)
{ {
Guard l(m_filterLock); Guard l(m_filterLock);
if (!m_filters.count(h)) if (!m_filters.count(h))
{
cwatch << "FFF" << _f << h.abridged();
m_filters.insert(make_pair(h, _f)); m_filters.insert(make_pair(h, _f));
}
} }
return installWatch(h); return installWatch(h);
} }
@ -226,7 +229,7 @@ void Client::uninstallWatch(unsigned _i)
void Client::noteChanged(h256Set const& _filters) void Client::noteChanged(h256Set const& _filters)
{ {
Guard l(m_filterLock); Guard l(m_filterLock);
// cnote << "noteChanged(" << _filters << ")"; cnote << "noteChanged(" << _filters << ")";
// accrue all changes left in each filter into the watches. // accrue all changes left in each filter into the watches.
for (auto& i: m_watches) for (auto& i: m_watches)
if (_filters.count(i.second.id)) if (_filters.count(i.second.id))

6
libethereum/Client.h

@ -34,7 +34,7 @@
#include <libdevcore/Worker.h> #include <libdevcore/Worker.h>
#include <libevm/FeeStructure.h> #include <libevm/FeeStructure.h>
#include <libp2p/Common.h> #include <libp2p/Common.h>
#include "BlockChain.h" #include "CanonBlockChain.h"
#include "TransactionQueue.h" #include "TransactionQueue.h"
#include "State.h" #include "State.h"
#include "CommonNet.h" #include "CommonNet.h"
@ -228,7 +228,7 @@ public:
/// Get the object representing the current state of Ethereum. /// Get the object representing the current state of Ethereum.
dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; } dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; }
/// Get the object representing the current canonical blockchain. /// Get the object representing the current canonical blockchain.
BlockChain const& blockChain() const { return m_bc; } CanonBlockChain const& blockChain() const { return m_bc; }
// Mining stuff: // Mining stuff:
@ -308,7 +308,7 @@ private:
State asOf(unsigned _h) const; State asOf(unsigned _h) const;
VersionChecker m_vc; ///< Dummy object to check & update the protocol version. VersionChecker m_vc; ///< Dummy object to check & update the protocol version.
BlockChain m_bc; ///< Maintains block database. CanonBlockChain m_bc; ///< Maintains block database.
TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain.
BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported).

7
libethereum/LogFilter.cpp

@ -27,6 +27,13 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
std::ostream& dev::operator<<(std::ostream& _out, LogFilter const& _s)
{
// TODO
_out << "(@" << _s.m_addresses << "#" << _s.m_topics << ">" << _s.m_earliest << "-" << _s.m_latest << "< +" << _s.m_skip << "^" << _s.m_max << ")";
return _out;
}
void LogFilter::streamRLP(RLPStream& _s) const void LogFilter::streamRLP(RLPStream& _s) const
{ {
_s.appendList(6) << m_addresses << m_topics << m_earliest << m_latest << m_max << m_skip; _s.appendList(6) << m_addresses << m_topics << m_earliest << m_latest << m_max << m_skip;

16
libethereum/LogFilter.h

@ -28,6 +28,15 @@
namespace dev namespace dev
{ {
namespace eth
{
class LogFilter;
}
/// Simple stream output for the StateDiff.
std::ostream& operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
namespace eth namespace eth
{ {
@ -56,14 +65,17 @@ public:
LogFilter withEarliest(int _e) { m_earliest = _e; return *this; } LogFilter withEarliest(int _e) { m_earliest = _e; return *this; }
LogFilter withLatest(int _e) { m_latest = _e; return *this; } LogFilter withLatest(int _e) { m_latest = _e; return *this; }
friend std::ostream& dev::operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
private: private:
AddressSet m_addresses; AddressSet m_addresses;
std::array<h256Set, 4> m_topics; std::array<h256Set, 4> m_topics;
int m_earliest = 0; int m_earliest = 0;
int m_latest = -1; int m_latest = -1;
unsigned m_max; unsigned m_max = 10;
unsigned m_skip; unsigned m_skip = 0;
}; };
} }
} }

13
libethereum/State.cpp

@ -35,6 +35,7 @@
#include "ExtVM.h" #include "ExtVM.h"
#include "Executive.h" #include "Executive.h"
#include "CachedAddressState.h" #include "CachedAddressState.h"
#include "CanonBlockChain.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -74,18 +75,16 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs):
paranoia("beginning of normal construction.", true); paranoia("beginning of normal construction.", true);
if (_bs == BaseState::Genesis) if (_bs == BaseState::CanonGenesis)
{ {
dev::eth::commit(genesisState(), m_db, m_state); dev::eth::commit(genesisState(), m_db, m_state);
m_db.commit(); m_db.commit();
paranoia("after DB commit of normal construction.", true); paranoia("after DB commit of normal construction.", true);
m_previousBlock = BlockChain::genesis(); m_previousBlock = CanonBlockChain::genesis();
} }
else else
{
m_previousBlock.setEmpty(); m_previousBlock.setEmpty();
}
resetCurrent(); resetCurrent();
@ -304,7 +303,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi)
// (Most recent state dump might end up being genesis.) // (Most recent state dump might end up being genesis.)
std::vector<h256> chain; std::vector<h256> chain;
while (bi.stateRoot != BlockChain::genesis().hash && m_db.lookup(bi.stateRoot).empty()) // while we don't have the state root of the latest block... while (bi.number != 0 && m_db.lookup(bi.stateRoot).empty()) // while we don't have the state root of the latest block...
{ {
chain.push_back(bi.hash); // push back for later replay. chain.push_back(bi.hash); // push back for later replay.
bi.populate(_bc.block(bi.parentHash)); // move to parent. bi.populate(_bc.block(bi.parentHash)); // move to parent.
@ -698,7 +697,7 @@ void State::commitToMine(BlockChain const& _bc)
RLPStream unclesData; RLPStream unclesData;
unsigned unclesCount = 0; unsigned unclesCount = 0;
if (m_previousBlock != BlockChain::genesis()) if (m_previousBlock.number != 0)
{ {
// Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations. // Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations.
// cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl; // cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl;
@ -800,7 +799,7 @@ void State::completeMine()
ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentTxs);
ret.appendRaw(m_currentUncles); ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes); ret.swapOut(m_currentBytes);
m_currentBlock.hash = sha3(m_currentBytes); 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() << ")";
// Quickly reset the transactions. // Quickly reset the transactions.

4
libethereum/State.h

@ -53,7 +53,7 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S=";
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; };
enum class BaseState { Empty, Genesis }; enum class BaseState { Empty, CanonGenesis };
/** /**
* @brief Model of the current state of the ledger. * @brief Model of the current state of the ledger.
@ -68,7 +68,7 @@ class State
public: public:
/// Construct state object. /// Construct state object.
State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::Genesis); State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::CanonGenesis);
/// Construct state object from arbitrary point in blockchain. /// Construct state object from arbitrary point in blockchain.
State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash); State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash);

2
libjsqrc/ethereumjs/bower.json

@ -1,7 +1,7 @@
{ {
"name": "ethereum.js", "name": "ethereum.js",
"namespace": "ethereum", "namespace": "ethereum",
"version": "0.0.11", "version": "0.0.13",
"description": "Ethereum Compatible JavaScript API", "description": "Ethereum Compatible JavaScript API",
"main": ["./dist/ethereum.js", "./dist/ethereum.min.js"], "main": ["./dist/ethereum.js", "./dist/ethereum.min.js"],
"dependencies": { "dependencies": {

377
libjsqrc/ethereumjs/dist/ethereum.js

@ -210,7 +210,7 @@ module.exports = {
}; };
},{"./const":2,"./formatters":6,"./types":10,"./utils":11,"./web3":12}],2:[function(require,module,exports){ },{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -238,9 +238,32 @@ if ("build" !== 'build') {/*
var BigNumber = require('bignumber.js'); // jshint ignore:line var BigNumber = require('bignumber.js'); // jshint ignore:line
*/} */}
var ETH_UNITS = [
'wei',
'Kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'ether',
'grand',
'Mether',
'Gether',
'Tether',
'Pether',
'Eether',
'Zether',
'Yether',
'Nether',
'Dether',
'Vether',
'Uether'
];
module.exports = { module.exports = {
ETH_PADDING: 32, ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4, ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }
}; };
@ -368,6 +391,11 @@ var addFunctionsToContract = function (contract, desc, address) {
var addEventRelatedPropertiesToContract = function (contract, desc, address) { var addEventRelatedPropertiesToContract = function (contract, desc, address) {
contract.address = address; contract.address = address;
contract._onWatchEventResult = function (data) {
var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));
var parser = eventImpl.outputParser(matchingEvent);
return parser(data);
};
Object.defineProperty(contract, 'topic', { Object.defineProperty(contract, 'topic', {
get: function() { get: function() {
@ -386,8 +414,12 @@ 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 signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl(address, signature, e); var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params); var o = event.apply(null, params);
o._onWatchEventResult = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o); return web3.eth.watch(o);
}; };
@ -455,7 +487,7 @@ var contract = function (address, desc) {
module.exports = contract; module.exports = contract;
},{"./abi":1,"./event":4,"./utils":11,"./web3":12}],4:[function(require,module,exports){ },{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -481,6 +513,16 @@ module.exports = contract;
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
/// filter inputs array && returns only indexed (or not) inputs
/// @param inputs array
/// @param bool if result should be an array of indexed params on not
/// @returns array of (not?) indexed params
var filterInputs = function (inputs, indexed) {
return inputs.filter(function (current) {
return current.indexed === indexed;
});
};
var inputWithName = function (inputs, name) { var inputWithName = function (inputs, name) {
var index = utils.findIndex(inputs, function (input) { var index = utils.findIndex(inputs, function (input) {
return input.name === name; return input.name === name;
@ -496,7 +538,7 @@ var inputWithName = function (inputs, name) {
var indexedParamsToTopics = function (event, indexed) { var indexedParamsToTopics = function (event, indexed) {
// sort keys? // sort keys?
return Object.keys(indexed).map(function (key) { return Object.keys(indexed).map(function (key) {
var inputs = [inputWithName(event.inputs, key)]; var inputs = [inputWithName(filterInputs(event.inputs, true), key)];
var value = indexed[key]; var value = indexed[key];
if (value instanceof Array) { if (value instanceof Array) {
@ -508,7 +550,7 @@ var indexedParamsToTopics = function (event, indexed) {
}); });
}; };
var implementationOfEvent = function (address, signature, event) { var inputParser = function (address, signature, 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) {
@ -523,10 +565,66 @@ var implementationOfEvent = function (address, signature, event) {
}; };
}; };
module.exports = implementationOfEvent; var getArgumentsObject = function (inputs, indexed, notIndexed) {
var indexedCopy = indexed.slice();
var notIndexedCopy = notIndexed.slice();
return inputs.reduce(function (acc, current) {
var value;
if (current.indexed)
value = indexed.splice(0, 1)[0];
else
value = notIndexed.splice(0, 1)[0];
acc[current.name] = value;
return acc;
}, {});
};
var outputParser = function (event) {
return function (output) {
var result = {
event: utils.extractDisplayName(event.name),
number: output.number,
args: {}
};
if (!output.topic) {
return result;
}
var indexedOutputs = filterInputs(event.inputs, true);
var indexedData = "0x" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join("");
var indexedRes = abi.formatOutput(indexedOutputs, indexedData);
var notIndexedOutputs = filterInputs(event.inputs, false);
var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);
result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);
return result;
};
};
var getMatchingEvent = function (events, payload) {
for (var i = 0; i < events.length; i++) {
var signature = abi.eventSignatureFromAscii(events[i].name);
if (signature === payload.topic[0]) {
return events[i];
}
}
return undefined;
};
module.exports = {
inputParser: inputParser,
outputParser: outputParser,
getMatchingEvent: getMatchingEvent
};
},{"./abi":1,"./utils":11}],5:[function(require,module,exports){ },{"./abi":1,"./utils":12}],5:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -565,6 +663,8 @@ var Filter = function(options, impl) {
if (options.topics) { if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead'); console.warn('"topics" is deprecated, use "topic" instead');
} }
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties // evaluate lazy properties
options = { options = {
@ -583,7 +683,7 @@ var Filter = function(options, impl) {
this.callbacks = []; this.callbacks = [];
this.id = impl.newFilter(options); this.id = impl.newFilter(options);
web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
}; };
/// alias for changed* /// alias for changed*
@ -603,7 +703,8 @@ Filter.prototype.changed = function(callback) {
Filter.prototype.trigger = function(messages) { Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) { for (var i = 0; i < this.callbacks.length; i++) {
for (var j = 0; j < messages.length; j++) { for (var j = 0; j < messages.length; j++) {
this.callbacks[i].call(this, messages[j]); var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];
this.callbacks[i].call(this, message);
} }
} }
}; };
@ -626,7 +727,7 @@ Filter.prototype.logs = function () {
module.exports = Filter; module.exports = Filter;
},{"./web3":12}],6:[function(require,module,exports){ },{"./web3":13}],6:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -782,7 +883,7 @@ module.exports = {
}; };
},{"./const":2,"./utils":11}],7:[function(require,module,exports){ },{"./const":2,"./utils":12}],7:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -815,40 +916,16 @@ var HttpSyncProvider = function (host) {
this.host = host || 'http://localhost:8080'; this.host = host || 'http://localhost:8080';
}; };
/// Transforms inner message to proper jsonrpc object
/// @param inner message object
/// @returns jsonrpc object
function formatJsonRpcObject(object) {
return {
jsonrpc: '2.0',
method: object.call,
params: object.args,
id: object._id
};
}
/// Transforms jsonrpc object to inner message
/// @param incoming jsonrpc message
/// @returns inner message object
function formatJsonRpcMessage(message) {
var object = JSON.parse(message);
return {
_id: object.id,
data: object.result,
error: object.error
};
}
HttpSyncProvider.prototype.send = function (payload) { HttpSyncProvider.prototype.send = function (payload) {
var data = formatJsonRpcObject(payload); //var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.open('POST', this.host, false); request.open('POST', this.host, false);
request.send(JSON.stringify(data)); request.send(JSON.stringify(payload));
// check request.status // check request.status
return request.responseText; var result = request.responseText;
return JSON.parse(result);
}; };
module.exports = HttpSyncProvider; module.exports = HttpSyncProvider;
@ -871,6 +948,73 @@ module.exports = HttpSyncProvider;
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 jsonrpc.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var messageId = 1;
/// Should be called to valid json create payload object
/// @param method of jsonrpc call, required
/// @param params, an array of method params, optional
/// @returns valid jsonrpc payload object
var toPayload = function (method, params) {
if (!method)
console.error('jsonrpc method should be specified!');
return {
jsonrpc: '2.0',
method: method,
params: params || [],
id: messageId++
};
};
/// Should be called to check if jsonrpc response is valid
/// @returns true if response is valid, otherwise false
var isValidResponse = function (response) {
return !!response &&
!response.error &&
response.jsonrpc === '2.0' &&
typeof response.id === 'number' &&
response.result !== undefined; // only undefined is not valid json object
};
/// Should be called to create batch payload object
/// @param messages, an array of objects with method (required) and params (optional) fields
var toBatchPayload = function (messages) {
return messages.map(function (message) {
return toPayload(message.method, message.params);
});
};
module.exports = {
toPayload: toPayload,
isValidResponse: isValidResponse,
toBatchPayload: toBatchPayload
};
},{}],9:[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 providermanager.js /** @file providermanager.js
* @authors: * @authors:
* Jeffrey Wilcke <jeff@ethdev.com> * Jeffrey Wilcke <jeff@ethdev.com>
@ -880,7 +1024,9 @@ module.exports = HttpSyncProvider;
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3'); // jshint ignore:line var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
/** /**
* Provider manager object prototype * Provider manager object prototype
@ -894,25 +1040,35 @@ var web3 = require('./web3'); // jshint ignore:line
var ProviderManager = function() { var ProviderManager = function() {
this.polls = []; this.polls = [];
this.provider = undefined; this.provider = undefined;
this.id = 1;
var self = this; var self = this;
var poll = function () { var poll = function () {
if (self.provider) { if (self.provider) {
self.polls.forEach(function (data) { var pollsBatch = self.polls.map(function (data) {
data.data._id = self.id; return data.data;
self.id++; });
var result = self.provider.send(data.data);
var payload = jsonrpc.toBatchPayload(pollsBatch);
result = JSON.parse(result); var results = self.provider.send(payload);
self.polls.forEach(function (data, index) {
var result = results[index];
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return;
}
result = result.result;
// dont call the callback if result is not an array, or empty one // dont call the callback if result is not an array, or empty one
if (result.error || !(result.result instanceof Array) || result.result.length === 0) { if (!(result instanceof Array) || result.length === 0) {
return; return;
} }
data.callback(result.result); data.callback(result);
}); });
} }
setTimeout(poll, 1000); setTimeout(poll, 1000);
}; };
@ -920,22 +1076,19 @@ var ProviderManager = function() {
}; };
/// sends outgoing requests /// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) { ProviderManager.prototype.send = function(data) {
var payload = jsonrpc.toPayload(data.method, data.params);
data.args = data.args || [];
data._id = this.id++;
if (this.provider === undefined) { if (this.provider === undefined) {
console.error('provider is not set'); console.error('provider is not set');
return null; return null;
} }
//TODO: handle error here? var result = this.provider.send(payload);
var result = this.provider.send(data);
result = JSON.parse(result);
if (result.error) { if (!jsonrpc.isValidResponse(result)) {
console.log(result.error); console.log(result);
return null; return null;
} }
@ -966,7 +1119,7 @@ ProviderManager.prototype.stopPolling = function (pollId) {
module.exports = ProviderManager; module.exports = ProviderManager;
},{"./web3":12}],9:[function(require,module,exports){ },{"./jsonrpc":8,"./web3":13}],10:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -994,13 +1147,14 @@ var QtSyncProvider = function () {
}; };
QtSyncProvider.prototype.send = function (payload) { QtSyncProvider.prototype.send = function (payload) {
return navigator.qt.callMethod(JSON.stringify(payload)); var result = navigator.qt.callMethod(JSON.stringify(payload));
return JSON.parse(result);
}; };
module.exports = QtSyncProvider; module.exports = QtSyncProvider;
},{}],10:[function(require,module,exports){ },{}],11:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1081,7 +1235,7 @@ module.exports = {
}; };
},{"./formatters":6}],11:[function(require,module,exports){ },{"./formatters":6}],12:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1104,6 +1258,8 @@ module.exports = {
* @date 2015 * @date 2015
*/ */
var c = require('./const');
/// Finds first index of array element matching pattern /// Finds first index of array element matching pattern
/// @param array /// @param array
/// @param callback pattern /// @param callback pattern
@ -1166,7 +1322,7 @@ var extractDisplayName = function (name) {
var extractTypeName = function (name) { var extractTypeName = function (name) {
/// TODO: make it invulnerable /// TODO: make it invulnerable
var length = name.indexOf('('); var length = name.indexOf('(');
return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : ""; return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : "";
}; };
/// Filters all function from input abi /// Filters all function from input abi
@ -1185,6 +1341,32 @@ var filterEvents = function (json) {
}); });
}; };
/// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int
/// TODO: add tests for it!
var toEth = function (str) {
var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = c.ETH_UNITS;
while (val > 3000 && unit < units.length - 1)
{
val /= 1000;
unit++;
}
var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
var replaceFunction = function($0, $1, $2) {
return $1 + ',' + $2;
};
while (true) {
var o = s;
s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction);
if (o === s)
break;
}
return s + ' ' + units[unit];
};
module.exports = { module.exports = {
findIndex: findIndex, findIndex: findIndex,
toAscii: toAscii, toAscii: toAscii,
@ -1192,11 +1374,12 @@ module.exports = {
extractDisplayName: extractDisplayName, extractDisplayName: extractDisplayName,
extractTypeName: extractTypeName, extractTypeName: extractTypeName,
filterFunctions: filterFunctions, filterFunctions: filterFunctions,
filterEvents: filterEvents filterEvents: filterEvents,
toEth: toEth
}; };
},{}],12:[function(require,module,exports){ },{"./const":2}],13:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
@ -1228,28 +1411,6 @@ if ("build" !== 'build') {/*
var utils = require('./utils'); var utils = require('./utils');
var ETH_UNITS = [
'wei',
'Kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'ether',
'grand',
'Mether',
'Gether',
'Tether',
'Pether',
'Eether',
'Zether',
'Yether',
'Nether',
'Dether',
'Vether',
'Uether'
];
/// @returns an array of objects describing web3 api methods /// @returns an array of objects describing web3 api methods
var web3Methods = function () { var web3Methods = function () {
return [ return [
@ -1357,8 +1518,8 @@ var setupMethods = function (obj, methods) {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call; var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({ return web3.provider.send({
call: call, method: call,
args: args params: args
}); });
}; };
}); });
@ -1371,15 +1532,15 @@ var setupProperties = function (obj, properties) {
var proto = {}; var proto = {};
proto.get = function () { proto.get = function () {
return web3.provider.send({ return web3.provider.send({
call: property.getter method: property.getter
}); });
}; };
if (property.setter) { if (property.setter) {
proto.set = function (val) { proto.set = function (val) {
return web3.provider.send({ return web3.provider.send({
call: property.setter, method: property.setter,
args: [val] params: [val]
}); });
}; };
} }
@ -1412,29 +1573,7 @@ var web3 = {
}, },
/// used to transform value/string to eth string /// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int toEth: utils.toEth,
toEth: function(str) {
var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = ETH_UNITS;
while (val > 3000 && unit < units.length - 1)
{
val /= 1000;
unit++;
}
var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
var replaceFunction = function($0, $1, $2) {
return $1 + ',' + $2;
};
while (true) {
var o = s;
s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction);
if (o === s)
break;
}
return s + ' ' + units[unit];
},
/// eth object prototype /// eth object prototype
eth: { eth: {
@ -1470,11 +1609,6 @@ var web3 = {
return new web3.filter(filter, shhWatch); return new web3.filter(filter, shhWatch);
} }
}, },
/// @returns true if provider is installed
haveProvider: function() {
return !!web3.provider.provider;
}
}; };
/// setups all api methods /// setups all api methods
@ -1497,14 +1631,13 @@ var shhWatch = {
setupMethods(shhWatch, shhWatchMethods()); setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) { web3.setProvider = function(provider) {
//provider.onmessage = messageHandler; // there will be no async calls, to remove
web3.provider.set(provider); web3.provider.set(provider);
}; };
module.exports = web3; module.exports = web3;
},{"./utils":11}],"web3":[function(require,module,exports){ },{"./utils":12}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3'); var web3 = require('./lib/web3');
var ProviderManager = require('./lib/providermanager'); var ProviderManager = require('./lib/providermanager');
web3.provider = new ProviderManager(); web3.provider = new ProviderManager();
@ -1517,7 +1650,7 @@ web3.abi = require('./lib/abi');
module.exports = web3; module.exports = web3;
},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":8,"./lib/qtsync":9,"./lib/web3":12}]},{},["web3"]) },{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"])
//# sourceMappingURL=ethereum.js.map //# sourceMappingURL=ethereum.js.map

22
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

66
libjsqrc/ethereumjs/example/event_inc.html

@ -0,0 +1,66 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="js/bignumber.js/bignumber.min.js"></script>
<script type="text/javascript" src="../dist/ethereum.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080'));
var source = "" +
"contract Contract { " +
" event Incremented(bool indexed odd, uint x); " +
" function Contract() { " +
" x = 69; " +
" } " +
" function inc() { " +
" ++x; " +
" Incremented(x % 2 == 1, x); " +
" } " +
" uint x; " +
"}";
var desc = [{
"type":"event",
"name":"Incremented",
"inputs": [{"name":"odd","type":"bool","indexed":true},{"name":"x","type":"uint","indexed":false}],
}, {
"type":"function",
"name":"inc",
"inputs": [],
"outputs": []
}];
var address;
var contract;
var update = function (x) {
document.getElementById('result').innerText = JSON.stringify(x);
};
var createContract = function () {
address = web3.eth.transact({code: web3.eth.solidity(source)});
contract = web3.eth.contract(address, desc);
contract.Incremented({odd: true}).changed(update);
};
var callContract = function () {
contract.call().inc();
};
</script>
</head>
<body>
<div>
<button type="button" onClick="createContract();">create contract</button>
</div>
<div>
<button type="button" onClick="callContract();">test1</button>
</div>
<div id="result">
</div>
</body>
</html>

23
libjsqrc/ethereumjs/lib/const.js

@ -25,9 +25,32 @@ if (process.env.NODE_ENV !== 'build') {
var BigNumber = require('bignumber.js'); // jshint ignore:line var BigNumber = require('bignumber.js'); // jshint ignore:line
} }
var ETH_UNITS = [
'wei',
'Kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'ether',
'grand',
'Mether',
'Gether',
'Tether',
'Pether',
'Eether',
'Zether',
'Yether',
'Nether',
'Dether',
'Vether',
'Uether'
];
module.exports = { module.exports = {
ETH_PADDING: 32, ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4, ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }
}; };

11
libjsqrc/ethereumjs/lib/contract.js

@ -120,6 +120,11 @@ var addFunctionsToContract = function (contract, desc, address) {
var addEventRelatedPropertiesToContract = function (contract, desc, address) { var addEventRelatedPropertiesToContract = function (contract, desc, address) {
contract.address = address; contract.address = address;
contract._onWatchEventResult = function (data) {
var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));
var parser = eventImpl.outputParser(matchingEvent);
return parser(data);
};
Object.defineProperty(contract, 'topic', { Object.defineProperty(contract, 'topic', {
get: function() { get: function() {
@ -138,8 +143,12 @@ 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 signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl(address, signature, e); var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params); var o = event.apply(null, params);
o._onWatchEventResult = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o); return web3.eth.watch(o);
}; };

72
libjsqrc/ethereumjs/lib/event.js

@ -23,6 +23,16 @@
var abi = require('./abi'); var abi = require('./abi');
var utils = require('./utils'); var utils = require('./utils');
/// filter inputs array && returns only indexed (or not) inputs
/// @param inputs array
/// @param bool if result should be an array of indexed params on not
/// @returns array of (not?) indexed params
var filterInputs = function (inputs, indexed) {
return inputs.filter(function (current) {
return current.indexed === indexed;
});
};
var inputWithName = function (inputs, name) { var inputWithName = function (inputs, name) {
var index = utils.findIndex(inputs, function (input) { var index = utils.findIndex(inputs, function (input) {
return input.name === name; return input.name === name;
@ -38,7 +48,7 @@ var inputWithName = function (inputs, name) {
var indexedParamsToTopics = function (event, indexed) { var indexedParamsToTopics = function (event, indexed) {
// sort keys? // sort keys?
return Object.keys(indexed).map(function (key) { return Object.keys(indexed).map(function (key) {
var inputs = [inputWithName(event.inputs, key)]; var inputs = [inputWithName(filterInputs(event.inputs, true), key)];
var value = indexed[key]; var value = indexed[key];
if (value instanceof Array) { if (value instanceof Array) {
@ -50,7 +60,7 @@ var indexedParamsToTopics = function (event, indexed) {
}); });
}; };
var implementationOfEvent = function (address, signature, event) { var inputParser = function (address, signature, 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) {
@ -65,5 +75,61 @@ var implementationOfEvent = function (address, signature, event) {
}; };
}; };
module.exports = implementationOfEvent; var getArgumentsObject = function (inputs, indexed, notIndexed) {
var indexedCopy = indexed.slice();
var notIndexedCopy = notIndexed.slice();
return inputs.reduce(function (acc, current) {
var value;
if (current.indexed)
value = indexed.splice(0, 1)[0];
else
value = notIndexed.splice(0, 1)[0];
acc[current.name] = value;
return acc;
}, {});
};
var outputParser = function (event) {
return function (output) {
var result = {
event: utils.extractDisplayName(event.name),
number: output.number,
args: {}
};
if (!output.topic) {
return result;
}
var indexedOutputs = filterInputs(event.inputs, true);
var indexedData = "0x" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join("");
var indexedRes = abi.formatOutput(indexedOutputs, indexedData);
var notIndexedOutputs = filterInputs(event.inputs, false);
var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);
result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);
return result;
};
};
var getMatchingEvent = function (events, payload) {
for (var i = 0; i < events.length; i++) {
var signature = abi.eventSignatureFromAscii(events[i].name);
if (signature === payload.topic[0]) {
return events[i];
}
}
return undefined;
};
module.exports = {
inputParser: inputParser,
outputParser: outputParser,
getMatchingEvent: getMatchingEvent
};

7
libjsqrc/ethereumjs/lib/filter.js

@ -36,6 +36,8 @@ var Filter = function(options, impl) {
if (options.topics) { if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead'); console.warn('"topics" is deprecated, use "topic" instead');
} }
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties // evaluate lazy properties
options = { options = {
@ -54,7 +56,7 @@ var Filter = function(options, impl) {
this.callbacks = []; this.callbacks = [];
this.id = impl.newFilter(options); this.id = impl.newFilter(options);
web3.provider.startPolling({call: impl.changed, args: [this.id]}, this.id, this.trigger.bind(this)); web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
}; };
/// alias for changed* /// alias for changed*
@ -74,7 +76,8 @@ Filter.prototype.changed = function(callback) {
Filter.prototype.trigger = function(messages) { Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) { for (var i = 0; i < this.callbacks.length; i++) {
for (var j = 0; j < messages.length; j++) { for (var j = 0; j < messages.length; j++) {
this.callbacks[i].call(this, messages[j]); var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];
this.callbacks[i].call(this, message);
} }
} }
}; };

32
libjsqrc/ethereumjs/lib/httpsync.js

@ -30,40 +30,16 @@ var HttpSyncProvider = function (host) {
this.host = host || 'http://localhost:8080'; this.host = host || 'http://localhost:8080';
}; };
/// Transforms inner message to proper jsonrpc object
/// @param inner message object
/// @returns jsonrpc object
function formatJsonRpcObject(object) {
return {
jsonrpc: '2.0',
method: object.call,
params: object.args,
id: object._id
};
}
/// Transforms jsonrpc object to inner message
/// @param incoming jsonrpc message
/// @returns inner message object
function formatJsonRpcMessage(message) {
var object = JSON.parse(message);
return {
_id: object.id,
data: object.result,
error: object.error
};
}
HttpSyncProvider.prototype.send = function (payload) { HttpSyncProvider.prototype.send = function (payload) {
var data = formatJsonRpcObject(payload); //var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.open('POST', this.host, false); request.open('POST', this.host, false);
request.send(JSON.stringify(data)); request.send(JSON.stringify(payload));
// check request.status // check request.status
return request.responseText; var result = request.responseText;
return JSON.parse(result);
}; };
module.exports = HttpSyncProvider; module.exports = HttpSyncProvider;

65
libjsqrc/ethereumjs/lib/jsonrpc.js

@ -0,0 +1,65 @@
/*
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 jsonrpc.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var messageId = 1;
/// Should be called to valid json create payload object
/// @param method of jsonrpc call, required
/// @param params, an array of method params, optional
/// @returns valid jsonrpc payload object
var toPayload = function (method, params) {
if (!method)
console.error('jsonrpc method should be specified!');
return {
jsonrpc: '2.0',
method: method,
params: params || [],
id: messageId++
};
};
/// Should be called to check if jsonrpc response is valid
/// @returns true if response is valid, otherwise false
var isValidResponse = function (response) {
return !!response &&
!response.error &&
response.jsonrpc === '2.0' &&
typeof response.id === 'number' &&
response.result !== undefined; // only undefined is not valid json object
};
/// Should be called to create batch payload object
/// @param messages, an array of objects with method (required) and params (optional) fields
var toBatchPayload = function (messages) {
return messages.map(function (message) {
return toPayload(message.method, message.params);
});
};
module.exports = {
toPayload: toPayload,
isValidResponse: isValidResponse,
toBatchPayload: toBatchPayload
};

45
libjsqrc/ethereumjs/lib/providermanager.js

@ -23,7 +23,9 @@
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3'); // jshint ignore:line var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
/** /**
* Provider manager object prototype * Provider manager object prototype
@ -37,25 +39,35 @@ var web3 = require('./web3'); // jshint ignore:line
var ProviderManager = function() { var ProviderManager = function() {
this.polls = []; this.polls = [];
this.provider = undefined; this.provider = undefined;
this.id = 1;
var self = this; var self = this;
var poll = function () { var poll = function () {
if (self.provider) { if (self.provider) {
self.polls.forEach(function (data) { var pollsBatch = self.polls.map(function (data) {
data.data._id = self.id; return data.data;
self.id++; });
var result = self.provider.send(data.data);
var payload = jsonrpc.toBatchPayload(pollsBatch);
result = JSON.parse(result); var results = self.provider.send(payload);
self.polls.forEach(function (data, index) {
var result = results[index];
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return;
}
result = result.result;
// dont call the callback if result is not an array, or empty one // dont call the callback if result is not an array, or empty one
if (result.error || !(result.result instanceof Array) || result.result.length === 0) { if (!(result instanceof Array) || result.length === 0) {
return; return;
} }
data.callback(result.result); data.callback(result);
}); });
} }
setTimeout(poll, 1000); setTimeout(poll, 1000);
}; };
@ -63,22 +75,19 @@ var ProviderManager = function() {
}; };
/// sends outgoing requests /// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) { ProviderManager.prototype.send = function(data) {
var payload = jsonrpc.toPayload(data.method, data.params);
data.args = data.args || [];
data._id = this.id++;
if (this.provider === undefined) { if (this.provider === undefined) {
console.error('provider is not set'); console.error('provider is not set');
return null; return null;
} }
//TODO: handle error here? var result = this.provider.send(payload);
var result = this.provider.send(data);
result = JSON.parse(result);
if (result.error) { if (!jsonrpc.isValidResponse(result)) {
console.log(result.error); console.log(result);
return null; return null;
} }

3
libjsqrc/ethereumjs/lib/qtsync.js

@ -25,7 +25,8 @@ var QtSyncProvider = function () {
}; };
QtSyncProvider.prototype.send = function (payload) { QtSyncProvider.prototype.send = function (payload) {
return navigator.qt.callMethod(JSON.stringify(payload)); var result = navigator.qt.callMethod(JSON.stringify(payload));
return JSON.parse(result);
}; };
module.exports = QtSyncProvider; module.exports = QtSyncProvider;

33
libjsqrc/ethereumjs/lib/utils.js

@ -20,6 +20,8 @@
* @date 2015 * @date 2015
*/ */
var c = require('./const');
/// Finds first index of array element matching pattern /// Finds first index of array element matching pattern
/// @param array /// @param array
/// @param callback pattern /// @param callback pattern
@ -82,7 +84,7 @@ var extractDisplayName = function (name) {
var extractTypeName = function (name) { var extractTypeName = function (name) {
/// TODO: make it invulnerable /// TODO: make it invulnerable
var length = name.indexOf('('); var length = name.indexOf('(');
return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)) : ""; return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : "";
}; };
/// Filters all function from input abi /// Filters all function from input abi
@ -101,6 +103,32 @@ var filterEvents = function (json) {
}); });
}; };
/// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int
/// TODO: add tests for it!
var toEth = function (str) {
var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = c.ETH_UNITS;
while (val > 3000 && unit < units.length - 1)
{
val /= 1000;
unit++;
}
var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
var replaceFunction = function($0, $1, $2) {
return $1 + ',' + $2;
};
while (true) {
var o = s;
s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction);
if (o === s)
break;
}
return s + ' ' + units[unit];
};
module.exports = { module.exports = {
findIndex: findIndex, findIndex: findIndex,
toAscii: toAscii, toAscii: toAscii,
@ -108,6 +136,7 @@ module.exports = {
extractDisplayName: extractDisplayName, extractDisplayName: extractDisplayName,
extractTypeName: extractTypeName, extractTypeName: extractTypeName,
filterFunctions: filterFunctions, filterFunctions: filterFunctions,
filterEvents: filterEvents filterEvents: filterEvents,
toEth: toEth
}; };

62
libjsqrc/ethereumjs/lib/web3.js

@ -29,28 +29,6 @@ if (process.env.NODE_ENV !== 'build') {
var utils = require('./utils'); var utils = require('./utils');
var ETH_UNITS = [
'wei',
'Kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'ether',
'grand',
'Mether',
'Gether',
'Tether',
'Pether',
'Eether',
'Zether',
'Yether',
'Nether',
'Dether',
'Vether',
'Uether'
];
/// @returns an array of objects describing web3 api methods /// @returns an array of objects describing web3 api methods
var web3Methods = function () { var web3Methods = function () {
return [ return [
@ -158,8 +136,8 @@ var setupMethods = function (obj, methods) {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call; var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({ return web3.provider.send({
call: call, method: call,
args: args params: args
}); });
}; };
}); });
@ -172,15 +150,15 @@ var setupProperties = function (obj, properties) {
var proto = {}; var proto = {};
proto.get = function () { proto.get = function () {
return web3.provider.send({ return web3.provider.send({
call: property.getter method: property.getter
}); });
}; };
if (property.setter) { if (property.setter) {
proto.set = function (val) { proto.set = function (val) {
return web3.provider.send({ return web3.provider.send({
call: property.setter, method: property.setter,
args: [val] params: [val]
}); });
}; };
} }
@ -213,29 +191,7 @@ var web3 = {
}, },
/// used to transform value/string to eth string /// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int toEth: utils.toEth,
toEth: function(str) {
var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = ETH_UNITS;
while (val > 3000 && unit < units.length - 1)
{
val /= 1000;
unit++;
}
var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);
var replaceFunction = function($0, $1, $2) {
return $1 + ',' + $2;
};
while (true) {
var o = s;
s = s.replace(/(\d)(\d\d\d[\.\,])/, replaceFunction);
if (o === s)
break;
}
return s + ' ' + units[unit];
},
/// eth object prototype /// eth object prototype
eth: { eth: {
@ -271,11 +227,6 @@ var web3 = {
return new web3.filter(filter, shhWatch); return new web3.filter(filter, shhWatch);
} }
}, },
/// @returns true if provider is installed
haveProvider: function() {
return !!web3.provider.provider;
}
}; };
/// setups all api methods /// setups all api methods
@ -298,7 +249,6 @@ var shhWatch = {
setupMethods(shhWatch, shhWatchMethods()); setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) { web3.setProvider = function(provider) {
//provider.onmessage = messageHandler; // there will be no async calls, to remove
web3.provider.set(provider); web3.provider.set(provider);
}; };

2
libjsqrc/ethereumjs/package.json

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

438
libjsqrc/ethereumjs/test/abi.parsers.js → libjsqrc/ethereumjs/test/abi.inputParser.js

@ -423,443 +423,5 @@ describe('abi', function() {
}); });
}); });
describe('outputParser', function() {
it('should parse output string', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: "string" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'world'
);
});
it('should parse output uint', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output uint256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output uint128', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint128' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output int', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int128', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int128' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output hash', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output hash256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output hash160', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash160' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
// TODO shouldnt' the expected hash be shorter?
});
it('should parse output address', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'address' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output bool', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'bool' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true);
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false);
});
it('should parse output real', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'real' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1);
});
it('should parse output ureal', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'ureal' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
});
it('should parse multiple output strings', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: "string" },
{ type: "string" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[1],
'world'
);
});
it('should use proper method name', function () {
// given
var d = clone(description);
d[0].name = 'helloworld(int)';
d[0].outputs = [
{ type: "int" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
});
it('should parse multiple methods', function () {
// given
var d = [{
name: "test",
type: "function",
inputs: [{ type: "int" }],
outputs: [{ type: "int" }]
},{
name: "test2",
type: "function",
inputs: [{ type: "string" }],
outputs: [{ type: "string" }]
}];
// when
var parser = abi.outputParser(d);
//then
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test2("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
"hello"
);
});
it('should parse output array', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int[]' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][0],
5
);
assert.equal(parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][1],
6
);
});
it('should parse 0x value', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
});
it('should parse 0x value', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
});
});
}); });

461
libjsqrc/ethereumjs/test/abi.outputParser.js

@ -0,0 +1,461 @@
var assert = require('assert');
var BigNumber = require('bignumber.js');
var abi = require('../lib/abi.js');
var clone = function (object) { return JSON.parse(JSON.stringify(object)); };
var description = [{
"name": "test",
"type": "function",
"inputs": [{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}];
describe('abi', function() {
describe('outputParser', function() {
it('should parse output string', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: "string" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'world'
);
});
it('should parse output uint', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output uint256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output uint128', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint128' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
it('should parse output int', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int128', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int128' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output hash', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output hash256', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash256' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output hash160', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'hash160' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"
);
// TODO shouldnt' the expected hash be shorter?
});
it('should parse output address', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'address' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
it('should parse output bool', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'bool' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true);
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false);
});
it('should parse output real', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'real' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
assert.equal(parser.test("0xffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1);
});
it('should parse output ureal', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'ureal' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0x0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0x0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
});
it('should parse multiple output strings', function() {
// given
var d = clone(description);
d[0].outputs = [
{ type: "string" },
{ type: "string" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[1],
'world'
);
});
it('should use proper method name', function () {
// given
var d = clone(description);
d[0].name = 'helloworld(int)';
d[0].outputs = [
{ type: "int" }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
});
it('should parse multiple methods', function () {
// given
var d = [{
name: "test",
type: "function",
inputs: [{ type: "int" }],
outputs: [{ type: "int" }]
},{
name: "test2",
type: "function",
inputs: [{ type: "string" }],
outputs: [{ type: "string" }]
}];
// when
var parser = abi.outputParser(d);
//then
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test2("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
"hello"
);
});
it('should parse output array', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int[]' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][0],
5
);
assert.equal(parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][1],
6
);
});
it('should parse 0x value', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'int' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
});
it('should parse 0x value', function () {
// given
var d = clone(description);
d[0].outputs = [
{ type: 'uint' }
];
// when
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
});
});
});

2
libjsqrc/ethereumjs/test/db.methods.js

@ -1,7 +1,7 @@
var assert = require('assert'); var assert = require('assert');
var web3 = require('../index.js'); var web3 = require('../index.js');
var u = require('./utils.js'); var u = require('./test.utils.js');
describe('web3', function() { describe('web3', function() {
describe('db', function() { describe('db', function() {

2
libjsqrc/ethereumjs/test/eth.methods.js

@ -1,6 +1,6 @@
var assert = require('assert'); var assert = require('assert');
var web3 = require('../index.js'); var web3 = require('../index.js');
var u = require('./utils.js'); var u = require('./test.utils.js');
describe('web3', function() { describe('web3', function() {
describe('eth', function() { describe('eth', function() {

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

@ -0,0 +1,125 @@
var assert = require('assert');
var event = require('../lib/event.js');
var f = require('../lib/formatters.js');
describe('event', function () {
describe('inputParser', function () {
it('should create basic filter input object', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event.inputParser(address, signature, e);
var result = impl();
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 1);
assert.equal(result.topic[0], signature);
});
it('should create filter input object with options', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event.inputParser(address, signature, e);
var result = impl({}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 1);
assert.equal(result.topic[0], signature);
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
it('should create filter input object with indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event.inputParser(address, signature, e);
var result = impl({a: 4}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 2);
assert.equal(result.topic[0], signature);
assert.equal(result.topic[1], f.formatInputInt(4));
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
it('should create filter input object with an array of indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event.inputParser(address, signature, e);
var result = impl({a: [4, 69]}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 2);
assert.equal(result.topic[0], signature);
assert.equal(result.topic[1][0], f.formatInputInt(4));
assert.equal(result.topic[1][1], f.formatInputInt(69));
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
});
});

124
libjsqrc/ethereumjs/test/event.js

@ -1,124 +0,0 @@
var assert = require('assert');
var event = require('../lib/event.js');
var f = require('../lib/formatters.js');
describe('event', function () {
it('should create basic filter input object', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event(address, signature, e);
var result = impl();
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 1);
assert.equal(result.topic[0], signature);
});
it('should create filter input object with options', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event(address, signature, e);
var result = impl({}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 1);
assert.equal(result.topic[0], signature);
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
it('should create filter input object with indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event(address, signature, e);
var result = impl({a: 4}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 2);
assert.equal(result.topic[0], signature);
assert.equal(result.topic[1], f.formatInputInt(4));
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
it('should create filter input object with an array of indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
earliest: 1,
latest: 2,
offset: 3,
max: 4
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}]
};
// when
var impl = event(address, signature, e);
var result = impl({a: [4, 69]}, options);
// then
assert.equal(result.address, address);
assert.equal(result.topic.length, 2);
assert.equal(result.topic[0], signature);
assert.equal(result.topic[1][0], f.formatInputInt(4));
assert.equal(result.topic[1][1], f.formatInputInt(69));
assert.equal(result.earliest, options.earliest);
assert.equal(result.latest, options.latest);
assert.equal(result.offset, options.offset);
assert.equal(result.max, options.max);
});
});

81
libjsqrc/ethereumjs/test/event.outputParser.js

@ -0,0 +1,81 @@
var assert = require('assert');
var event = require('../lib/event.js');
describe('event', function () {
describe('outputParser', function () {
it('should parse basic event output object', function () {
// given
var output = {
"address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e",
"data":"0x000000000000000000000000000000000000000000000000000000000000004b",
"number":2,
"topic":[
"0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad",
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
};
var e = {
name: 'Event',
inputs: [{"name":"a","type":"bool","indexed":true},{"name":"b","type":"uint256","indexed":false}]
};
// when
var impl = event.outputParser(e);
var result = impl(output);
// then
assert.equal(result.event, 'Event');
assert.equal(result.number, 2);
assert.equal(Object.keys(result.args).length, 2);
assert.equal(result.args.a, true);
assert.equal(result.args.b, 75);
});
it('should parse event output object arguments in correct order', function () {
// given
var output = {
"address":"0x78dfc5983baecf65f73e3de3a96cee24e6b7981e",
"data": "0x" +
"000000000000000000000000000000000000000000000000000000000000004b" +
"000000000000000000000000000000000000000000000000000000000000004c" +
"0000000000000000000000000000000000000000000000000000000000000001",
"number":3,
"topic":[
"0x6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
};
var e = {
name: 'Event2',
inputs: [
{"name":"a","type":"bool","indexed":true},
{"name":"b","type":"int","indexed":false},
{"name":"c","type":"int","indexed":false},
{"name":"d","type":"int","indexed":true},
{"name":"e","type":"bool","indexed":false}
]
};
// when
var impl = event.outputParser(e);
var result = impl(output);
// then
assert.equal(result.event, 'Event2');
assert.equal(result.number, 3);
assert.equal(Object.keys(result.args).length, 5);
assert.equal(result.args.a, true);
assert.equal(result.args.b, 75);
assert.equal(result.args.c, 76);
assert.equal(result.args.d, 5);
assert.equal(result.args.e, true);
});
});
});

143
libjsqrc/ethereumjs/test/jsonrpc.isValidResponse.js

@ -0,0 +1,143 @@
var assert = require('assert');
var jsonrpc = require('../lib/jsonrpc');
describe('jsonrpc', function () {
describe('isValidResponse', function () {
it('should validate basic jsonrpc response', function () {
// given
var response = {
jsonrpc: '2.0',
id: 1,
result: []
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, true);
});
it('should validate basic undefined response', function () {
// given
var response = undefined;
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response without jsonrpc field', function () {
// given
var response = {
id: 1,
result: []
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response with wrong jsonrpc version', function () {
// given
var response = {
jsonrpc: '1.0',
id: 1,
result: []
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response without id number', function () {
// given
var response = {
jsonrpc: '2.0',
result: []
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response with wrong id field', function () {
// given
var response = {
jsonrpc: '2.0',
id: 'x',
result: []
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response without result field', function () {
// given
var response = {
jsonrpc: '2.0',
id: 1
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, false);
});
it('should validate jsonrpc response with result field === false', function () {
// given
var response = {
jsonrpc: '2.0',
id: 1,
result: false
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, true);
});
it('should validate jsonrpc response with result field === 0', function () {
// given
var response = {
jsonrpc: '2.0',
id: 1,
result: 0
};
// when
var valid = jsonrpc.isValidResponse(response);
// then
assert.equal(valid, true);
});
});
});

47
libjsqrc/ethereumjs/test/jsonrpc.toBatchPayload.js

@ -0,0 +1,47 @@
var assert = require('assert');
var jsonrpc = require('../lib/jsonrpc');
describe('jsonrpc', function () {
describe('toBatchPayload', function () {
it('should create basic batch payload', function () {
// given
var messages = [{
method: 'helloworld'
}, {
method: 'test2',
params: [1]
}];
// when
var payload = jsonrpc.toBatchPayload(messages);
// then
assert.equal(payload instanceof Array, true);
assert.equal(payload.length, 2);
assert.equal(payload[0].jsonrpc, '2.0');
assert.equal(payload[1].jsonrpc, '2.0');
assert.equal(payload[0].method, 'helloworld');
assert.equal(payload[1].method, 'test2');
assert.equal(payload[0].params instanceof Array, true);
assert.equal(payload[1].params.length, 1);
assert.equal(payload[1].params[0], 1);
assert.equal(typeof payload[0].id, 'number');
assert.equal(typeof payload[1].id, 'number');
assert.equal(payload[0].id + 1, payload[1].id);
});
it('should create batch payload for empty input array', function () {
// given
var messages = [];
// when
var payload = jsonrpc.toBatchPayload(messages);
// then
assert.equal(payload instanceof Array, true);
assert.equal(payload.length, 0);
});
});
});

40
libjsqrc/ethereumjs/test/jsonrpc.toPayload.js

@ -0,0 +1,40 @@
var assert = require('assert');
var jsonrpc = require('../lib/jsonrpc');
describe('jsonrpc', function () {
describe('toPayload', function () {
it('should create basic payload', function () {
// given
var method = 'helloworld';
// when
var payload = jsonrpc.toPayload(method);
// then
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, method);
assert.equal(payload.params instanceof Array, true);
assert.equal(payload.params.length, 0);
assert.equal(typeof payload.id, 'number');
});
it('should create payload with params', function () {
// given
var method = 'helloworld1';
var params = [123, 'test'];
// when
var payload = jsonrpc.toPayload(method, params);
// then
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, method);
assert.equal(payload.params.length, 2);
assert.equal(payload.params[0], params[0]);
assert.equal(payload.params[1], params[1]);
assert.equal(typeof payload.id, 'number');
});
});
});

2
libjsqrc/ethereumjs/test/shh.methods.js

@ -1,6 +1,6 @@
var assert = require('assert'); var assert = require('assert');
var web3 = require('../index.js'); var web3 = require('../index.js');
var u = require('./utils.js'); var u = require('./test.utils.js');
describe('web3', function() { describe('web3', function() {
describe('shh', function() { describe('shh', function() {

0
libjsqrc/ethereumjs/test/utils.js → libjsqrc/ethereumjs/test/test.utils.js

42
libjsqrc/ethereumjs/test/utils.extractDisplayName.js

@ -0,0 +1,42 @@
var assert = require('assert');
var utils = require('../lib/utils.js');
describe('utils', function () {
describe('extractDisplayName', function () {
it('should extract display name from method with no params', function () {
// given
var test = 'helloworld()';
// when
var displayName = utils.extractDisplayName(test);
// then
assert.equal(displayName, 'helloworld');
});
it('should extract display name from method with one param' , function () {
// given
var test = 'helloworld1(int)';
// when
var displayName = utils.extractDisplayName(test);
// then
assert.equal(displayName, 'helloworld1');
});
it('should extract display name from method with two params' , function () {
// given
var test = 'helloworld2(int,string)';
// when
var displayName = utils.extractDisplayName(test);
// then
assert.equal(displayName, 'helloworld2');
});
});
});

55
libjsqrc/ethereumjs/test/utils.extractTypeName.js

@ -0,0 +1,55 @@
var assert = require('assert');
var utils = require('../lib/utils.js');
describe('utils', function () {
describe('extractTypeName', function () {
it('should extract type name from method with no params', function () {
// given
var test = 'helloworld()';
// when
var typeName = utils.extractTypeName(test);
// then
assert.equal(typeName, '');
});
it('should extract type name from method with one param', function () {
// given
var test = 'helloworld1(int)';
// when
var typeName = utils.extractTypeName(test);
// then
assert.equal(typeName, 'int');
});
it('should extract type name from method with two params', function () {
// given
var test = 'helloworld2(int,string)';
// when
var typeName = utils.extractTypeName(test);
// then
assert.equal(typeName, 'int,string');
});
it('should extract type name from method with spaces between params', function () {
// given
var test = 'helloworld3(int, string)';
// when
var typeName = utils.extractTypeName(test);
// then
assert.equal(typeName, 'int,string');
});
});
});

2
libjsqrc/ethereumjs/test/web3.methods.js

@ -1,6 +1,6 @@
var assert = require('assert'); var assert = require('assert');
var web3 = require('../index.js'); var web3 = require('../index.js');
var u = require('./utils.js'); var u = require('./test.utils.js');
describe('web3', function() { describe('web3', function() {
u.methodExists(web3, 'sha3'); u.methodExists(web3, 'sha3');

12
libjsqrc/natspec.js

@ -29,10 +29,20 @@ var getContractMethods = function (address, abi) {
return web3.eth.contract(address, abi); return web3.eth.contract(address, abi);
}; };
var getMethodWithName = function(abi, name) {
for (var i = 0; i < abi.length; i++) {
if (abi[i].name === name) {
return abi[i];
}
}
console.warn('could not find method with name: ' + name);
return undefined;
};
/// Function called to get all contract method input variables /// Function called to get all contract method input variables
/// @returns hashmap with all contract's method input variables /// @returns hashmap with all contract's method input variables
var getContractInputParams = function (abi, methodName, params) { var getContractInputParams = function (abi, methodName, params) {
var method = web3.abi.getMethodWithName(abi, methodName); var method = getMethodWithName(abi, methodName);
return method.inputs.reduce(function (acc, current, index) { return method.inputs.reduce(function (acc, current, index) {
acc[current.name] = params[index]; acc[current.name] = params[index];
return acc; return acc;

2
libp2p/Capability.cpp

@ -39,7 +39,7 @@ Capability::Capability(Session* _s, HostCapabilityFace* _h, unsigned _idOffset):
void Capability::disable(std::string const& _problem) void Capability::disable(std::string const& _problem)
{ {
clogS(NetConnect) << "Disabling capability '" << m_host->name() << "'. Reason:" << _problem; clogS(NetWarn) << "DISABLE: Disabling capability '" << m_host->name() << "'. Reason:" << _problem;
m_enabled = false; m_enabled = false;
} }

6
libp2p/Host.cpp

@ -378,6 +378,8 @@ string Host::pocHost()
void Host::connect(std::string const& _addr, unsigned short _port) noexcept void Host::connect(std::string const& _addr, unsigned short _port) noexcept
{ {
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run) if (!m_run)
return; return;
@ -409,6 +411,8 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept
void Host::connect(bi::tcp::endpoint const& _ep) void Host::connect(bi::tcp::endpoint const& _ep)
{ {
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run) if (!m_run)
return; return;
@ -430,6 +434,8 @@ void Host::connect(bi::tcp::endpoint const& _ep)
void Host::connect(std::shared_ptr<Node> const& _n) void Host::connect(std::shared_ptr<Node> const& _n)
{ {
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run) if (!m_run)
return; return;

17
libp2p/Session.cpp

@ -273,24 +273,24 @@ bool Session::interpret(RLP const& _r)
} }
case PingPacket: case PingPacket:
{ {
clogS(NetTriviaSummary) << "Ping"; clogS(NetTriviaSummary) << "Ping";
RLPStream s; RLPStream s;
sealAndSend(prep(s, PongPacket)); sealAndSend(prep(s, PongPacket));
break; break;
} }
case PongPacket: case PongPacket:
m_info.lastPing = std::chrono::steady_clock::now() - m_ping; m_info.lastPing = std::chrono::steady_clock::now() - m_ping;
clogS(NetTriviaSummary) << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_info.lastPing).count() << " ms"; clogS(NetTriviaSummary) << "Latency: " << chrono::duration_cast<chrono::milliseconds>(m_info.lastPing).count() << " ms";
break; break;
case GetPeersPacket: case GetPeersPacket:
{ {
clogS(NetTriviaSummary) << "GetPeers"; clogS(NetTriviaSummary) << "GetPeers";
m_theyRequestedNodes = true; m_theyRequestedNodes = true;
serviceNodesRequest(); serviceNodesRequest();
break; break;
} }
case PeersPacket: case PeersPacket:
clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)"; clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
m_weRequestedNodes = false; m_weRequestedNodes = false;
for (unsigned i = 1; i < _r.itemCount(); ++i) for (unsigned i = 1; i < _r.itemCount(); ++i)
{ {
@ -369,8 +369,13 @@ bool Session::interpret(RLP const& _r)
{ {
auto id = _r[0].toInt<unsigned>(); auto id = _r[0].toInt<unsigned>();
for (auto const& i: m_capabilities) for (auto const& i: m_capabilities)
if (i.second->m_enabled && id >= i.second->m_idOffset && id - i.second->m_idOffset < i.second->hostCapability()->messageCount() && i.second->interpret(id - i.second->m_idOffset, _r)) if (id >= i.second->m_idOffset && id - i.second->m_idOffset < i.second->hostCapability()->messageCount())
return true; {
if (i.second->m_enabled)
return i.second->interpret(id - i.second->m_idOffset, _r);
else
return true;
}
return false; return false;
} }
} }

13
libqwebthree/QWebThree.cpp

@ -41,20 +41,9 @@ void QWebThree::clientDieing()
this->disconnect(); this->disconnect();
} }
static QString formatInput(QJsonObject const& _object)
{
QJsonObject res;
res["jsonrpc"] = QString::fromStdString("2.0");
res["method"] = _object["call"];
res["params"] = _object["args"];
res["id"] = _object["_id"];
return QString::fromUtf8(QJsonDocument(res).toJson());
}
QString QWebThree::callMethod(QString _json) QString QWebThree::callMethod(QString _json)
{ {
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); emit processData(_json, ""); // it's synchronous
emit processData(formatInput(f), ""); // it's synchronous
return m_response; return m_response;
} }

92
libserpent/compiler.cpp

@ -77,43 +77,12 @@ Node popwrap(Node node) {
return multiToken(nodelist, 2, node.metadata); return multiToken(nodelist, 2, node.metadata);
} }
// Grabs variables
mss getVariables(Node node, mss cur=mss()) {
Metadata m = node.metadata;
// Tokens don't contain any variables
if (node.type == TOKEN)
return cur;
// Don't descend into call fragments
else if (node.val == "lll")
return getVariables(node.args[1], cur);
// At global scope get/set/ref also declare
else if (node.val == "get" || node.val == "set" || node.val == "ref") {
if (node.args[0].type != TOKEN)
err("Variable name must be simple token,"
" not complex expression! " + printSimple(node.args[0]), m);
if (!cur.count(node.args[0].val)) {
cur[node.args[0].val] = utd(cur.size() * 32 + 32);
//std::cerr << node.args[0].val << " " << cur[node.args[0].val] << "\n";
}
}
// Recursively process children
for (unsigned i = 0; i < node.args.size(); i++) {
cur = getVariables(node.args[i], cur);
}
return cur;
}
// Turns LLL tree into tree of code fragments // Turns LLL tree into tree of code fragments
programData opcodeify(Node node, programData opcodeify(Node node,
programAux aux=Aux(), programAux aux=Aux(),
programVerticalAux vaux=verticalAux()) { programVerticalAux vaux=verticalAux()) {
std::string symb = "_"+mkUniqueToken(); std::string symb = "_"+mkUniqueToken();
Metadata m = node.metadata; Metadata m = node.metadata;
// Get variables
if (!aux.vars.size()) {
aux.vars = getVariables(node);
aux.nextVarMem = aux.vars.size() * 32 + 32;
}
// Numbers // Numbers
if (node.type == TOKEN) { if (node.type == TOKEN) {
return pd(aux, nodeToNumeric(node), 1); return pd(aux, nodeToNumeric(node), 1);
@ -121,6 +90,10 @@ programData opcodeify(Node node,
else if (node.val == "ref" || node.val == "get" || node.val == "set") { else if (node.val == "ref" || node.val == "get" || node.val == "set") {
std::string varname = node.args[0].val; std::string varname = node.args[0].val;
// Determine reference to variable // Determine reference to variable
if (!aux.vars.count(node.args[0].val)) {
aux.vars[node.args[0].val] = utd(aux.nextVarMem);
aux.nextVarMem += 32;
}
Node varNode = tkn(aux.vars[varname], m); Node varNode = tkn(aux.vars[varname], m);
//std::cerr << varname << " " << printSimple(varNode) << "\n"; //std::cerr << varname << " " << printSimple(varNode) << "\n";
// Set variable // Set variable
@ -173,8 +146,7 @@ programData opcodeify(Node node,
} }
// Comments do nothing // Comments do nothing
else if (node.val == "comment") { else if (node.val == "comment") {
Node* nodelist = nullptr; return pd(aux, astnode("_", m), 0);
return pd(aux, multiToken(nodelist, 0, m), 0);
} }
// Custom operation sequence // Custom operation sequence
// eg. (ops bytez id msize swap1 msize add 0 swap1 mstore) == alloc // eg. (ops bytez id msize swap1 msize add 0 swap1 mstore) == alloc
@ -371,7 +343,7 @@ Node buildFragmentTree(Node node) {
// Builds a dictionary mapping labels to variable names // Builds a dictionary mapping labels to variable names
programAux buildDict(Node program, programAux aux, int labelLength) { void buildDict(Node program, programAux &aux, int labelLength) {
Metadata m = program.metadata; Metadata m = program.metadata;
// Token // Token
if (program.type == TOKEN) { if (program.type == TOKEN) {
@ -388,30 +360,24 @@ programAux buildDict(Node program, programAux aux, int labelLength) {
} }
// A sub-program (ie. LLL) // A sub-program (ie. LLL)
else if (program.val == "____CODE") { else if (program.val == "____CODE") {
programAux auks = Aux(); int step = aux.step;
aux.step = 0;
for (unsigned i = 0; i < program.args.size(); i++) { for (unsigned i = 0; i < program.args.size(); i++) {
auks = buildDict(program.args[i], auks, labelLength); buildDict(program.args[i], aux, labelLength);
} }
for (std::map<std::string,std::string>::iterator it=auks.vars.begin(); aux.step += step;
it != auks.vars.end();
it++) {
aux.vars[(*it).first] = (*it).second;
}
aux.step += auks.step;
} }
// Normal sub-block // Normal sub-block
else { else {
for (unsigned i = 0; i < program.args.size(); i++) { for (unsigned i = 0; i < program.args.size(); i++) {
aux = buildDict(program.args[i], aux, labelLength); buildDict(program.args[i], aux, labelLength);
} }
} }
return aux;
} }
// Applies that dictionary // Applies that dictionary
Node substDict(Node program, programAux aux, int labelLength) { void substDict(Node program, programAux aux, int labelLength, std::vector<Node> &out) {
Metadata m = program.metadata; Metadata m = program.metadata;
std::vector<Node> out;
std::vector<Node> inner; std::vector<Node> inner;
if (program.type == TOKEN) { if (program.type == TOKEN) {
if (program.val[0] == '$') { if (program.val[0] == '$') {
@ -428,46 +394,32 @@ Node substDict(Node program, programAux aux, int labelLength) {
dist = decimalSub(end, start); dist = decimalSub(end, start);
inner = toByteArr(dist, m, labelLength); inner = toByteArr(dist, m, labelLength);
} }
out.push_back(astnode("_", inner, m)); for (unsigned i = 0; i < inner.size(); i++) out.push_back(inner[i]);
} }
else if (program.val[0] == '~') { } else if (program.val[0] == '~') { }
else if (isNumberLike(program)) { else if (isNumberLike(program)) {
inner = toByteArr(program.val, m); inner = toByteArr(program.val, m);
out.push_back(token("PUSH"+unsignedToDecimal(inner.size()))); out.push_back(token("PUSH"+unsignedToDecimal(inner.size())));
out.push_back(astnode("_", inner, m)); for (unsigned i = 0; i < inner.size(); i++) out.push_back(inner[i]);
} }
else return program; else out.push_back(program);
} }
else { else {
for (unsigned i = 0; i < program.args.size(); i++) { for (unsigned i = 0; i < program.args.size(); i++) {
Node n = substDict(program.args[i], aux, labelLength); substDict(program.args[i], aux, labelLength, out);
if (n.type == TOKEN || n.args.size()) out.push_back(n);
} }
} }
return astnode("_", out, m);
} }
// Compiled fragtree -> compiled fragtree without labels // Compiled fragtree -> compiled fragtree without labels
Node dereference(Node program) { std::vector<Node> dereference(Node program) {
int sz = treeSize(program) * 4; int sz = treeSize(program) * 4;
int labelLength = 1; int labelLength = 1;
while (sz >= 256) { labelLength += 1; sz /= 256; } while (sz >= 256) { labelLength += 1; sz /= 256; }
programAux aux = buildDict(program, Aux(), labelLength); programAux aux = Aux();
return substDict(program, aux, labelLength); buildDict(program, aux, labelLength);
}
// Dereferenced fragtree -> opcodes
std::vector<Node> flatten(Node derefed) {
std::vector<Node> o; std::vector<Node> o;
if (derefed.type == TOKEN) { substDict(program, aux, labelLength, o);
o.push_back(derefed);
}
else {
for (unsigned i = 0; i < derefed.args.size(); i++) {
std::vector<Node> oprime = flatten(derefed.args[i]);
for (unsigned j = 0; j < oprime.size(); j++) o.push_back(oprime[j]);
}
}
return o; return o;
} }
@ -512,12 +464,12 @@ std::vector<Node> deserialize(std::string ser) {
// Fragtree -> bin // Fragtree -> bin
std::string assemble(Node fragTree) { std::string assemble(Node fragTree) {
return serialize(flatten(dereference(fragTree))); return serialize(dereference(fragTree));
} }
// Fragtree -> tokens // Fragtree -> tokens
std::vector<Node> prettyAssemble(Node fragTree) { std::vector<Node> prettyAssemble(Node fragTree) {
return flatten(dereference(fragTree)); return dereference(fragTree);
} }
// LLL -> bin // LLL -> bin

5
libserpent/compiler.h

@ -8,14 +8,11 @@
#include "util.h" #include "util.h"
// Compiled fragtree -> compiled fragtree without labels // Compiled fragtree -> compiled fragtree without labels
Node dereference(Node program); std::vector<Node> dereference(Node program);
// LLL -> fragtree // LLL -> fragtree
Node buildFragmentTree(Node program); Node buildFragmentTree(Node program);
// Dereferenced fragtree -> opcodes
std::vector<Node> flatten(Node derefed);
// opcodes -> bin // opcodes -> bin
std::string serialize(std::vector<Node> codons); std::string serialize(std::vector<Node> codons);

7
libserpent/util.cpp

@ -5,7 +5,6 @@
#include "util.h" #include "util.h"
#include "bignum.h" #include "bignum.h"
#include <fstream> #include <fstream>
#include <string>
#include <cerrno> #include <cerrno>
//Token or value node constructor //Token or value node constructor
@ -260,7 +259,7 @@ std::string get_file_contents(std::string filename)
{ {
std::string contents; std::string contents;
in.seekg(0, std::ios::end); in.seekg(0, std::ios::end);
contents.resize((unsigned)in.tellg()); contents.resize(in.tellg());
in.seekg(0, std::ios::beg); in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size()); in.read(&contents[0], contents.size());
in.close(); in.close();
@ -274,7 +273,7 @@ void err(std::string errtext, Metadata met) {
std::string err = "Error (file \"" + met.file + "\", line " + std::string err = "Error (file \"" + met.file + "\", line " +
unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) + unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) +
"): " + errtext; "): " + errtext;
std::cerr << err << "\n"; std::cerr << err << std::endl;
throw(err); throw(err);
} }
@ -283,7 +282,7 @@ void warn(std::string errtext, Metadata met) {
std::string err = "Warning (file \"" + met.file + "\", line " + std::string err = "Warning (file \"" + met.file + "\", line " +
unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) + unsignedToDecimal(met.ln + 1) + ", char " + unsignedToDecimal(met.ch) +
"): " + errtext; "): " + errtext;
std::cerr << err << "\n"; std::cerr << err << std::endl;
} }
//Bin to hex //Bin to hex

45
libsolidity/AST.cpp

@ -133,7 +133,7 @@ void ContractDefinition::checkIllegalOverrides() const
FunctionDefinition const*& override = functions[name]; FunctionDefinition const*& override = functions[name];
if (!override) if (!override)
override = function.get(); override = function.get();
else if (override->isPublic() != function->isPublic() || else if (override->getVisibility() != function->getVisibility() ||
override->isDeclaredConst() != function->isDeclaredConst() || override->isDeclaredConst() != function->isDeclaredConst() ||
FunctionType(*override) != FunctionType(*function)) FunctionType(*override) != FunctionType(*function))
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature.")); BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
@ -475,6 +475,8 @@ void FunctionCall::checkTypeRequirements()
// number of non-mapping members // number of non-mapping members
if (m_arguments.size() != 1) if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion."));
if (!m_names.empty())
BOOST_THROW_EXCEPTION(createTypeError("Type conversion can't allow named arguments."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type.getActualType(); m_type = type.getActualType();
@ -487,9 +489,44 @@ void FunctionCall::checkTypeRequirements()
TypePointers const& parameterTypes = functionType->getParameterTypes(); TypePointers const& parameterTypes = functionType->getParameterTypes();
if (parameterTypes.size() != m_arguments.size()) if (parameterTypes.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) if (m_names.empty())
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); {
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
}
else
{
auto const& parameterNames = functionType->getParameterNames();
if (parameterNames.size() != m_names.size())
BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing."));
// check duplicate names
for (size_t i = 0; i < m_names.size(); i++) {
for (size_t j = i + 1; j < m_names.size(); j++) {
if (*m_names[i] == *m_names[j])
BOOST_THROW_EXCEPTION(createTypeError("Duplicate named argument."));
}
}
for (size_t i = 0; i < m_names.size(); i++) {
bool found = false;
for (size_t j = 0; j < parameterNames.size(); j++) {
if (parameterNames[j] == *m_names[i]) {
// check type convertible
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[j]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
found = true;
break;
}
}
if (!found)
BOOST_THROW_EXCEPTION(createTypeError("Named argument doesn't match function declaration."));
}
}
// @todo actually the return type should be an anonymous struct, // @todo actually the return type should be an anonymous struct,
// but we change it to the type of the first return value until we have structs // but we change it to the type of the first return value until we have structs
if (functionType->getReturnParameterTypes().empty()) if (functionType->getReturnParameterTypes().empty())

41
libsolidity/AST.h

@ -133,12 +133,17 @@ class Declaration: public ASTNode
{ {
public: public:
enum class LValueType { NONE, LOCAL, STORAGE }; enum class LValueType { NONE, LOCAL, STORAGE };
enum class Visibility { DEFAULT, PUBLIC, PROTECTED, PRIVATE };
Declaration(Location const& _location, ASTPointer<ASTString> const& _name): Declaration(Location const& _location, ASTPointer<ASTString> const& _name,
ASTNode(_location), m_name(_name), m_scope(nullptr) {} Visibility _visibility = Visibility::DEFAULT):
ASTNode(_location), m_name(_name), m_visibility(_visibility), m_scope(nullptr) {}
/// @returns the declared name. /// @returns the declared name.
ASTString const& getName() const { return *m_name; } ASTString const& getName() const { return *m_name; }
Visibility getVisibility() const { return m_visibility == Visibility::DEFAULT ? getDefaultVisibility() : m_visibility; }
bool isPublic() const { return getVisibility() == Visibility::PUBLIC; }
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope. /// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
/// Available only after name and type resolution step. /// Available only after name and type resolution step.
Declaration const* getScope() const { return m_scope; } Declaration const* getScope() const { return m_scope; }
@ -151,8 +156,12 @@ public:
/// @returns the lvalue type of expressions referencing this declaration /// @returns the lvalue type of expressions referencing this declaration
virtual LValueType getLValueType() const { return LValueType::NONE; } virtual LValueType getLValueType() const { return LValueType::NONE; }
protected:
virtual Visibility getDefaultVisibility() const { return Visibility::PUBLIC; }
private: private:
ASTPointer<ASTString> m_name; ASTPointer<ASTString> m_name;
Visibility m_visibility;
Declaration const* m_scope; Declaration const* m_scope;
}; };
@ -330,16 +339,15 @@ class FunctionDefinition: public Declaration, public VariableScope, public Docum
{ {
public: public:
FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name, FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name,
bool _isPublic, Declaration::Visibility _visibility, bool _isConstructor,
bool _isConstructor,
ASTPointer<ASTString> const& _documentation, ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters, ASTPointer<ParameterList> const& _parameters,
bool _isDeclaredConst, bool _isDeclaredConst,
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers, std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
ASTPointer<ParameterList> const& _returnParameters, ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body): ASTPointer<Block> const& _body):
Declaration(_location, _name), Documented(_documentation), Declaration(_location, _name, _visibility), Documented(_documentation),
m_isPublic(_isPublic), m_isConstructor(_isConstructor), m_isConstructor(_isConstructor),
m_parameters(_parameters), m_parameters(_parameters),
m_isDeclaredConst(_isDeclaredConst), m_isDeclaredConst(_isDeclaredConst),
m_functionModifiers(_modifiers), m_functionModifiers(_modifiers),
@ -350,7 +358,6 @@ public:
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override; virtual void accept(ASTConstVisitor& _visitor) const override;
bool isPublic() const { return m_isPublic; }
bool isConstructor() const { return m_isConstructor; } bool isConstructor() const { return m_isConstructor; }
bool isDeclaredConst() const { return m_isDeclaredConst; } bool isDeclaredConst() const { return m_isDeclaredConst; }
std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; } std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; }
@ -371,7 +378,6 @@ public:
std::string getCanonicalSignature() const; std::string getCanonicalSignature() const;
private: private:
bool m_isPublic;
bool m_isConstructor; bool m_isConstructor;
ASTPointer<ParameterList> m_parameters; ASTPointer<ParameterList> m_parameters;
bool m_isDeclaredConst; bool m_isDeclaredConst;
@ -388,10 +394,10 @@ class VariableDeclaration: public Declaration
{ {
public: public:
VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type, VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type,
ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false, ASTPointer<ASTString> const& _name, Visibility _visibility,
bool _isIndexed = false): bool _isStateVar = false, bool _isIndexed = false):
Declaration(_location, _name), m_typeName(_type), Declaration(_location, _name, _visibility), m_typeName(_type),
m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override; virtual void accept(ASTConstVisitor& _visitor) const override;
@ -404,13 +410,14 @@ public:
virtual LValueType getLValueType() const override; virtual LValueType getLValueType() const override;
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); } bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
bool isPublic() const { return m_isPublic; }
bool isStateVariable() const { return m_isStateVariable; } bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; } bool isIndexed() const { return m_isIndexed; }
protected:
Visibility getDefaultVisibility() const override { return Visibility::PROTECTED; }
private: private:
ASTPointer<TypeName> m_typeName; ///< can be empty ("var") ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
bool m_isPublic; ///< Whether there is an accessor for it or not
bool m_isStateVariable; ///< Whether or not this is a contract state variable bool m_isStateVariable; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events). bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
@ -956,14 +963,15 @@ class FunctionCall: public Expression
{ {
public: public:
FunctionCall(Location const& _location, ASTPointer<Expression> const& _expression, FunctionCall(Location const& _location, ASTPointer<Expression> const& _expression,
std::vector<ASTPointer<Expression>> const& _arguments): std::vector<ASTPointer<Expression>> const& _arguments, std::vector<ASTPointer<ASTString>> const& _names):
Expression(_location), m_expression(_expression), m_arguments(_arguments) {} Expression(_location), m_expression(_expression), m_arguments(_arguments), m_names(_names) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override; virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override;
Expression const& getExpression() const { return *m_expression; } Expression const& getExpression() const { return *m_expression; }
std::vector<ASTPointer<Expression const>> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; } std::vector<ASTPointer<Expression const>> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; }
std::vector<ASTPointer<ASTString>> const& getNames() const { return m_names; }
/// Returns true if this is not an actual function call, but an explicit type conversion /// Returns true if this is not an actual function call, but an explicit type conversion
/// or constructor call. /// or constructor call.
@ -972,6 +980,7 @@ public:
private: private:
ASTPointer<Expression> m_expression; ASTPointer<Expression> m_expression;
std::vector<ASTPointer<Expression>> m_arguments; std::vector<ASTPointer<Expression>> m_arguments;
std::vector<ASTPointer<ASTString>> m_names;
}; };
/** /**

4
libsolidity/Compiler.cpp

@ -240,10 +240,6 @@ bool Compiler::visit(VariableDeclaration const& _variableDeclaration)
m_context << m_context.getFunctionEntryLabel(_variableDeclaration); m_context << m_context.getFunctionEntryLabel(_variableDeclaration);
ExpressionCompiler::appendStateVariableAccessor(m_context, _variableDeclaration); ExpressionCompiler::appendStateVariableAccessor(m_context, _variableDeclaration);
unsigned sizeOnStack = _variableDeclaration.getType()->getSizeOnStack();
solAssert(sizeOnStack <= 15, "Stack too deep.");
m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP;
return false; return false;
} }

72
libsolidity/ExpressionCompiler.cpp

@ -22,6 +22,7 @@
#include <utility> #include <utility>
#include <numeric> #include <numeric>
#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
@ -194,6 +195,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
{ {
//@todo struct construction //@todo struct construction
solAssert(_functionCall.getArguments().size() == 1, ""); solAssert(_functionCall.getArguments().size() == 1, "");
solAssert(_functionCall.getNames().empty(), "");
Expression const& firstArgument = *_functionCall.getArguments().front(); Expression const& firstArgument = *_functionCall.getArguments().front();
firstArgument.accept(*this); firstArgument.accept(*this);
appendTypeConversion(*firstArgument.getType(), *_functionCall.getType()); appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
@ -201,8 +203,26 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else else
{ {
FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType()); FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType());
vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments(); TypePointers const& parameterTypes = function.getParameterTypes();
solAssert(arguments.size() == function.getParameterTypes().size(), ""); vector<ASTPointer<Expression const>> const& callArguments = _functionCall.getArguments();
vector<ASTPointer<ASTString>> const& callArgumentNames = _functionCall.getNames();
solAssert(callArguments.size() == parameterTypes.size(), "");
vector<ASTPointer<Expression const>> arguments;
if (callArgumentNames.empty())
// normal arguments
arguments = callArguments;
else
// named arguments
for (auto const& parameterName: function.getParameterNames())
{
bool found = false;
for (size_t j = 0; j < callArgumentNames.size() && !found; j++)
if ((found = (parameterName == *callArgumentNames[j])))
// we found the actual parameter position
arguments.push_back(callArguments[j]);
solAssert(found, "");
}
switch (function.getLocation()) switch (function.getLocation())
{ {
@ -823,26 +843,58 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ
return length; return length;
} }
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
Expression const& _expression, unsigned _memoryOffset) Location const& _location, unsigned _memoryOffset)
{ {
_expression.accept(*this); appendTypeConversion(_type, _expectedType, true);
appendTypeConversion(*_expression.getType(), _expectedType, true);
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());
if (c_numBytes == 0 || c_numBytes > 32) if (c_numBytes == 0 || c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError() BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_expression.getLocation()) << errinfo_sourceLocation(_location)
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); << errinfo_comment("Type " + _expectedType.toString() + " not yet supported."));
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING;
bool const c_padToWords = true; bool const c_padToWords = true;
return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords);
} }
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
Expression const& _expression,
unsigned _memoryOffset)
{
_expression.accept(*this);
return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset);
}
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
{ {
m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); FunctionType thisType(_varDecl);
solAssert(m_currentLValue.isInStorage(), ""); solAssert(thisType.getReturnParameterTypes().size() == 1, "");
m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true); TypePointer const& resultType = thisType.getReturnParameterTypes().front();
unsigned sizeOnStack;
unsigned length = 0;
TypePointers const& params = thisType.getParameterTypes();
// move arguments to memory
for (TypePointer const& param: boost::adaptors::reverse(params))
length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length);
// retrieve the position of the mapping
m_context << m_context.getStorageLocationOfVariable(_varDecl);
for (TypePointer const& param: params)
{
// move offset to memory
CompilerUtils(m_context).storeInMemory(length);
unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize());
length -= argLen;
m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;
}
m_currentLValue = LValue(m_context, LValue::STORAGE, *resultType);
m_currentLValue.retrieveValue(resultType, Location(), true);
sizeOnStack = resultType->getSizeOnStack();
solAssert(sizeOnStack <= 15, "Stack too deep.");
m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP;
} }
ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType,

4
libsolidity/ExpressionCompiler.h

@ -97,6 +97,10 @@ private:
unsigned appendArgumentCopyToMemory(TypePointers const& _types, unsigned appendArgumentCopyToMemory(TypePointers const& _types,
std::vector<ASTPointer<Expression const>> const& _arguments, std::vector<ASTPointer<Expression const>> const& _arguments,
unsigned _memoryOffset = 0); unsigned _memoryOffset = 0);
/// Appends code that copies a type to memory.
/// @returns the number of bytes copied to memory
unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
Location const& _location, unsigned _memoryOffset = 0);
/// Appends code that evaluates a single expression and copies it to memory (with optional offset). /// Appends code that evaluates a single expression and copies it to memory (with optional offset).
/// @returns the number of bytes copied to memory /// @returns the number of bytes copied to memory
unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression,

89
libsolidity/Parser.cpp

@ -131,27 +131,19 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
} }
while (m_scanner->getCurrentToken() == Token::COMMA); while (m_scanner->getCurrentToken() == Token::COMMA);
expectToken(Token::LBRACE); expectToken(Token::LBRACE);
bool visibilityIsPublic = true;
while (true) while (true)
{ {
Token::Value currentToken = m_scanner->getCurrentToken(); Token::Value currentToken = m_scanner->getCurrentToken();
if (currentToken == Token::RBRACE) if (currentToken == Token::RBRACE)
break; break;
else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE)
{
visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC);
m_scanner->next();
expectToken(Token::COLON);
}
else if (currentToken == Token::FUNCTION) else if (currentToken == Token::FUNCTION)
functions.push_back(parseFunctionDefinition(visibilityIsPublic, name.get())); functions.push_back(parseFunctionDefinition(name.get()));
else if (currentToken == Token::STRUCT) else if (currentToken == Token::STRUCT)
structs.push_back(parseStructDefinition()); structs.push_back(parseStructDefinition());
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING || else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
Token::isElementaryTypeName(currentToken)) Token::isElementaryTypeName(currentToken))
{ {
VarDeclParserOptions options; VarDeclParserOptions options;
options.isPublic = visibilityIsPublic;
options.isStateVariable = true; options.isStateVariable = true;
stateVariables.push_back(parseVariableDeclaration(options)); stateVariables.push_back(parseVariableDeclaration(options));
expectToken(Token::SEMICOLON); expectToken(Token::SEMICOLON);
@ -177,7 +169,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
if (m_scanner->getCurrentToken() == Token::LPAREN) if (m_scanner->getCurrentToken() == Token::LPAREN)
{ {
m_scanner->next(); m_scanner->next();
arguments = parseFunctionCallArguments(); arguments = parseFunctionCallListArguments();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RPAREN); expectToken(Token::RPAREN);
} }
@ -186,7 +178,22 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
return nodeFactory.createNode<InheritanceSpecifier>(name, arguments); return nodeFactory.createNode<InheritanceSpecifier>(name, arguments);
} }
ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, ASTString const* _contractName) Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
{
Declaration::Visibility visibility;
if (_token == Token::PUBLIC)
visibility = Declaration::Visibility::PUBLIC;
else if (_token == Token::PROTECTED)
visibility = Declaration::Visibility::PROTECTED;
else if (_token == Token::PRIVATE)
visibility = Declaration::Visibility::PRIVATE;
else
solAssert(false, "Invalid visibility specifier.");
m_scanner->next();
return visibility;
}
ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
{ {
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
ASTPointer<ASTString> docstring; ASTPointer<ASTString> docstring;
@ -201,16 +208,24 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
name = expectIdentifierToken(); name = expectIdentifierToken();
ASTPointer<ParameterList> parameters(parseParameterList()); ASTPointer<ParameterList> parameters(parseParameterList());
bool isDeclaredConst = false; bool isDeclaredConst = false;
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
vector<ASTPointer<ModifierInvocation>> modifiers; vector<ASTPointer<ModifierInvocation>> modifiers;
while (true) while (true)
{ {
if (m_scanner->getCurrentToken() == Token::CONST) Token::Value token = m_scanner->getCurrentToken();
if (token == Token::CONST)
{ {
isDeclaredConst = true; isDeclaredConst = true;
m_scanner->next(); m_scanner->next();
} }
else if (m_scanner->getCurrentToken() == Token::IDENTIFIER) else if (token == Token::IDENTIFIER)
modifiers.push_back(parseModifierInvocation()); modifiers.push_back(parseModifierInvocation());
else if (Token::isVisibilitySpecifier(token))
{
if (visibility != Declaration::Visibility::DEFAULT)
BOOST_THROW_EXCEPTION(createParserError("Multiple visibility specifiers."));
visibility = parseVisibilitySpecifier(token);
}
else else
break; break;
} }
@ -226,7 +241,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
ASTPointer<Block> block = parseBlock(); ASTPointer<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block); nodeFactory.setEndPositionFromNode(block);
bool const c_isConstructor = (_contractName && *name == *_contractName); bool const c_isConstructor = (_contractName && *name == *_contractName);
return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, c_isConstructor, docstring, return nodeFactory.createNode<FunctionDefinition>(name, visibility, c_isConstructor, docstring,
parameters, isDeclaredConst, modifiers, parameters, isDeclaredConst, modifiers,
returnParameters, block); returnParameters, block);
} }
@ -253,14 +268,18 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOp
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
ASTPointer<TypeName> type = parseTypeName(_options.allowVar); ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
bool isIndexed = false; bool isIndexed = false;
if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED) Token::Value token = m_scanner->getCurrentToken();
if (_options.allowIndexed && token == Token::INDEXED)
{ {
isIndexed = true; isIndexed = true;
m_scanner->next(); m_scanner->next();
} }
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
if (_options.isStateVariable && Token::isVisibilitySpecifier(token))
visibility = parseVisibilitySpecifier(token);
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(),
_options.isPublic, _options.isStateVariable, visibility, _options.isStateVariable,
isIndexed); isIndexed);
} }
@ -313,7 +332,7 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
if (m_scanner->getCurrentToken() == Token::LPAREN) if (m_scanner->getCurrentToken() == Token::LPAREN)
{ {
m_scanner->next(); m_scanner->next();
arguments = parseFunctionCallArguments(); arguments = parseFunctionCallListArguments();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RPAREN); expectToken(Token::RPAREN);
} }
@ -573,7 +592,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
ASTPointer<Expression> expression = parseUnaryExpression(); ASTPointer<Expression> expression = parseUnaryExpression();
int precedence = Token::precedence(m_scanner->getCurrentToken()); int precedence = Token::precedence(m_scanner->getCurrentToken());
for (; precedence >= _minPrecedence; --precedence) for (; precedence >= _minPrecedence; --precedence)
{
while (Token::precedence(m_scanner->getCurrentToken()) == precedence) while (Token::precedence(m_scanner->getCurrentToken()) == precedence)
{ {
Token::Value op = m_scanner->getCurrentToken(); Token::Value op = m_scanner->getCurrentToken();
@ -582,7 +600,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
nodeFactory.setEndPositionFromNode(right); nodeFactory.setEndPositionFromNode(right);
expression = nodeFactory.createNode<BinaryOperation>(expression, op, right); expression = nodeFactory.createNode<BinaryOperation>(expression, op, right);
} }
}
return expression; return expression;
} }
@ -648,10 +665,12 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression()
case Token::LPAREN: case Token::LPAREN:
{ {
m_scanner->next(); m_scanner->next();
vector<ASTPointer<Expression>> arguments = parseFunctionCallArguments(); vector<ASTPointer<Expression>> arguments;
vector<ASTPointer<ASTString>> names;
std::tie(arguments, names) = parseFunctionCallArguments();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expectToken(Token::RPAREN); expectToken(Token::RPAREN);
expression = nodeFactory.createNode<FunctionCall>(expression, arguments); expression = nodeFactory.createNode<FunctionCall>(expression, arguments, names);
} }
break; break;
default: default:
@ -704,7 +723,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
return expression; return expression;
} }
vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments() vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
{ {
vector<ASTPointer<Expression>> arguments; vector<ASTPointer<Expression>> arguments;
if (m_scanner->getCurrentToken() != Token::RPAREN) if (m_scanner->getCurrentToken() != Token::RPAREN)
@ -719,6 +738,32 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
return arguments; return arguments;
} }
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::parseFunctionCallArguments()
{
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret;
Token::Value token = m_scanner->getCurrentToken();
if (token == Token::LBRACE)
{
// call({arg1 : 1, arg2 : 2 })
expectToken(Token::LBRACE);
while (m_scanner->getCurrentToken() != Token::RBRACE)
{
ret.second.push_back(expectIdentifierToken());
expectToken(Token::COLON);
ret.first.push_back(parseExpression());
if (m_scanner->getCurrentToken() == Token::COMMA)
expectToken(Token::COMMA);
else
break;
}
expectToken(Token::RBRACE);
}
else
ret.first = parseFunctionCallListArguments();
return ret;
}
bool Parser::peekVariableDefinition() bool Parser::peekVariableDefinition()
{ {

7
libsolidity/Parser.h

@ -48,7 +48,6 @@ private:
struct VarDeclParserOptions { struct VarDeclParserOptions {
VarDeclParserOptions() {} VarDeclParserOptions() {}
bool allowVar = false; bool allowVar = false;
bool isPublic = false;
bool isStateVariable = false; bool isStateVariable = false;
bool allowIndexed = false; bool allowIndexed = false;
}; };
@ -58,7 +57,8 @@ private:
ASTPointer<ImportDirective> parseImportDirective(); ASTPointer<ImportDirective> parseImportDirective();
ASTPointer<ContractDefinition> parseContractDefinition(); ASTPointer<ContractDefinition> parseContractDefinition();
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier(); ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName); Declaration::Visibility parseVisibilitySpecifier(Token::Value _token);
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
ASTPointer<StructDefinition> parseStructDefinition(); ASTPointer<StructDefinition> parseStructDefinition();
ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
ASTPointer<ModifierDefinition> parseModifierDefinition(); ASTPointer<ModifierDefinition> parseModifierDefinition();
@ -81,7 +81,8 @@ private:
ASTPointer<Expression> parseUnaryExpression(); ASTPointer<Expression> parseUnaryExpression();
ASTPointer<Expression> parseLeftHandSideExpression(); ASTPointer<Expression> parseLeftHandSideExpression();
ASTPointer<Expression> parsePrimaryExpression(); ASTPointer<Expression> parsePrimaryExpression();
std::vector<ASTPointer<Expression>> parseFunctionCallArguments(); std::vector<ASTPointer<Expression>> parseFunctionCallListArguments();
std::pair<std::vector<ASTPointer<Expression>>, std::vector<ASTPointer<ASTString>>> parseFunctionCallArguments();
///@} ///@}
///@{ ///@{

2
libsolidity/Token.h

@ -165,6 +165,7 @@ namespace solidity
K(NEW, "new", 0) \ K(NEW, "new", 0) \
K(PUBLIC, "public", 0) \ K(PUBLIC, "public", 0) \
K(PRIVATE, "private", 0) \ K(PRIVATE, "private", 0) \
K(PROTECTED, "protected", 0) \
K(RETURN, "return", 0) \ K(RETURN, "return", 0) \
K(RETURNS, "returns", 0) \ K(RETURNS, "returns", 0) \
K(STRUCT, "struct", 0) \ K(STRUCT, "struct", 0) \
@ -376,6 +377,7 @@ public:
static bool isUnaryOp(Value op) { return (NOT <= op && op <= DELETE) || op == ADD || op == SUB; } static bool isUnaryOp(Value op) { return (NOT <= op && op <= DELETE) || op == ADD || op == SUB; }
static bool isCountOp(Value op) { return op == INC || op == DEC; } static bool isCountOp(Value op) { return op == INC || op == DEC; }
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); } static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; }
// Returns a string corresponding to the JS token string // Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or NULL if the token doesn't // (.e., "<" for the token LT) or NULL if the token doesn't

23
libsolidity/Types.cpp

@ -621,11 +621,24 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal
FunctionType::FunctionType(VariableDeclaration const& _varDecl): FunctionType::FunctionType(VariableDeclaration const& _varDecl):
m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl) m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl)
{ {
TypePointers params({}); TypePointers params;
vector<string> paramNames({}); vector<string> paramNames;
TypePointers retParams({_varDecl.getType()}); TypePointers retParams;
vector<string> retParamNames({ _varDecl.getName()}); vector<string> retParamNames;
// for now, no input parameters LTODO: change for some things like mapping TypePointer varDeclType = _varDecl.getType();
auto mappingType = dynamic_cast<MappingType const*>(varDeclType.get());
auto returnType = varDeclType;
while (mappingType != nullptr)
{
params.push_back(mappingType->getKeyType());
paramNames.push_back("");
returnType = mappingType->getValueType();
mappingType = dynamic_cast<MappingType const*>(mappingType->getValueType().get());
}
retParams.push_back(returnType);
retParamNames.push_back("");
swap(params, m_parameterTypes); swap(params, m_parameterTypes);
swap(paramNames, m_parameterNames); swap(paramNames, m_parameterNames);

7
libsolidity/grammar.txt

@ -1,14 +1,15 @@
ContractDefinition = 'contract' Identifier ContractDefinition = 'contract' Identifier
( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )? ( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )?
'{' ContractPart* '}' '{' ContractPart* '}'
ContractPart = VariableDeclaration ';' | StructDefinition | ModifierDefinition | ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition
FunctionDefinition | 'public:' | 'private:'
InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )? InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )?
StructDefinition = 'struct' Identifier '{' StructDefinition = 'struct' Identifier '{'
( VariableDeclaration (';' VariableDeclaration)* )? '} ( VariableDeclaration (';' VariableDeclaration)* )? '}
StateVariableDeclaration = TypeName ( 'public' | 'protected' | 'private' )? Identifier ';'
ModifierDefinition = 'modifier' Identifier ParameterList? Block ModifierDefinition = 'modifier' Identifier ParameterList? Block
FunctionDefinition = 'function' Identifier ParameterList ( Identifier | 'constant' )* FunctionDefinition = 'function' Identifier ParameterList
( Identifier | 'constant' | 'public' | 'protected' | 'private' )*
( 'returns' ParameterList )? Block ( 'returns' ParameterList )? Block
ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')' ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings // semantic restriction: mappings and structs (recursively) containing mappings

7
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -28,7 +28,7 @@
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libwhisper/Message.h> #include <libwhisper/Message.h>
#include <libwhisper/WhisperHost.h> #include <libwhisper/WhisperHost.h>
#include <libserpent/funcs.h> #include <libserpent/funcs.h>
@ -342,7 +342,10 @@ std::string WebThreeStubServerBase::eth_call(Json::Value const& _json)
Json::Value WebThreeStubServerBase::eth_changed(int const& _id) Json::Value WebThreeStubServerBase::eth_changed(int const& _id)
{ {
return toJson(client()->checkWatch(_id)); auto entries = client()->checkWatch(_id);
if (entries.size())
cnote << "FIRING WATCH" << _id << entries.size();
return toJson(entries);
} }
std::string WebThreeStubServerBase::eth_codeAt(string const& _address) std::string WebThreeStubServerBase::eth_codeAt(string const& _address)

4
libweb3jsonrpc/WebThreeStubServerBase.h

@ -36,9 +36,9 @@ namespace dev
{ {
class WebThreeNetworkFace; class WebThreeNetworkFace;
class KeyPair; class KeyPair;
struct TransactionSkeleton;
namespace eth namespace eth
{ {
struct TransactionSkeleton;
class Interface; class Interface;
} }
namespace shh namespace shh
@ -122,7 +122,7 @@ public:
std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; } std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; }
protected: protected:
virtual bool authenticate(dev::TransactionSkeleton const& _t); virtual bool authenticate(dev::eth::TransactionSkeleton const& _t);
protected: protected:
virtual dev::eth::Interface* client() = 0; virtual dev::eth::Interface* client() = 0;

45
macdeployfix.sh

@ -0,0 +1,45 @@
#!/bin/bash
# solves problem with macdeployqt on Qt 5.4 RC
# http://qt-project.org/forums/viewthread/50118
BUILD_FOLDER_PATH=$1
BUILD_QML_FOLDER_PATH="$BUILD_FOLDER_PATH/Resources/qml"
BUILD_PLUGINS_FOLDER_PATH="$BUILD_FOLDER_PATH/PlugIns"
if [ ! -d ${BUILD_QML_FOLDER_PATH} ]; then
# we are not using any qml files
# gracefully exit
exit 0
fi
declare -a BROKEN_FILES;
k=0;
for j in $(find ${BUILD_QML_FOLDER_PATH} -name *.dylib); do
BROKEN_FILES[${k}]=$j
((k=k+1))
done
for i in "${BROKEN_FILES[@]}"; do
REPLACE_STRING="$BUILD_FOLDER_PATH/"
APP_CONTENT_FILE=${i//$REPLACE_STRING/""}
IFS='/' read -a array <<< "$APP_CONTENT_FILE"
LENGTH=${#array[@]}
LAST_ITEM_INDEX=$((LENGTH-1))
FILE=${array[${LENGTH} - 1]}
ORIGINE_PATH=$(find ${BUILD_PLUGINS_FOLDER_PATH} -name ${FILE})
ORIGINE_PATH=${ORIGINE_PATH//$REPLACE_STRING/""}
s=""
for((l=0;l<${LAST_ITEM_INDEX};l++)) do
s=$s"../"
done
s=$s$ORIGINE_PATH
echo "s: $s"
REMOVE_BROKEN_ALIAS=$(rm -rf $i)
RESULT=$(ln -s $s $i)
done

14
mix/AppContext.cpp

@ -27,15 +27,16 @@
#include <QQmlComponent> #include <QQmlComponent>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQuickWindow> #include <QWindow>
#include "CodeModel.h" #include "CodeModel.h"
#include "FileIo.h" #include "FileIo.h"
#include "ClientModel.h" #include "ClientModel.h"
#include "CodeEditorExtensionManager.h" #include "CodeEditorExtensionManager.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "AppContext.h"
#include "QEther.h" #include "QEther.h"
#include "QVariableDefinition.h"
#include "HttpServer.h" #include "HttpServer.h"
#include "AppContext.h"
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -49,6 +50,7 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_codeModel.reset(new CodeModel(this)); m_codeModel.reset(new CodeModel(this));
m_clientModel.reset(new ClientModel(this)); m_clientModel.reset(new ClientModel(this));
m_fileIo.reset(new FileIo()); m_fileIo.reset(new FileIo());
connect(QApplication::clipboard(), &QClipboard::dataChanged, [this] { emit clipboardChanged();});
} }
AppContext::~AppContext() AppContext::~AppContext()
@ -82,7 +84,7 @@ void AppContext::load()
qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager");
qmlRegisterType<HttpServer>("HttpServer", 1, 0, "HttpServer"); qmlRegisterType<HttpServer>("HttpServer", 1, 0, "HttpServer");
m_applicationEngine->load(QUrl("qrc:/qml/main.qml")); m_applicationEngine->load(QUrl("qrc:/qml/main.qml"));
QQuickWindow *window = qobject_cast<QQuickWindow *>(m_applicationEngine->rootObjects().at(0)); QWindow *window = qobject_cast<QWindow *>(m_applicationEngine->rootObjects().at(0));
window->setIcon(QIcon(":/res/mix_256x256x32.png")); window->setIcon(QIcon(":/res/mix_256x256x32.png"));
appLoaded(); appLoaded();
} }
@ -105,6 +107,12 @@ void AppContext::displayMessageDialog(QString _title, QString _message)
QMetaObject::invokeMethod(dialogWin, "open"); QMetaObject::invokeMethod(dialogWin, "open");
} }
QString AppContext::clipboard() const
{
QClipboard *clipboard = QApplication::clipboard();
return clipboard->text();
}
void AppContext::toClipboard(QString _text) void AppContext::toClipboard(QString _text)
{ {
QClipboard *clipboard = QApplication::clipboard(); QClipboard *clipboard = QApplication::clipboard();

4
mix/AppContext.h

@ -48,6 +48,7 @@ class FileIo;
class AppContext: public QObject class AppContext: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString clipboard READ clipboard WRITE toClipboard NOTIFY clipboardChanged)
public: public:
AppContext(QQmlApplicationEngine* _engine); AppContext(QQmlApplicationEngine* _engine);
@ -64,10 +65,13 @@ public:
void displayMessageDialog(QString _title, QString _message); void displayMessageDialog(QString _title, QString _message);
/// Copy text to clipboard /// Copy text to clipboard
Q_INVOKABLE void toClipboard(QString _text); Q_INVOKABLE void toClipboard(QString _text);
/// Get text from clipboard
QString clipboard() const;
signals: signals:
/// Triggered once components have been loaded /// Triggered once components have been loaded
void appLoaded(); void appLoaded();
void clipboardChanged();
private: private:
QQmlApplicationEngine* m_applicationEngine; //owned by app QQmlApplicationEngine* m_applicationEngine; //owned by app

41
mix/ClientModel.cpp

@ -22,14 +22,16 @@
#include <QDebug> #include <QDebug>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QStandardPaths>
#include <jsonrpccpp/server.h> #include <jsonrpccpp/server.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include "AppContext.h" #include "AppContext.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "QContractDefinition.h" #include "QContractDefinition.h"
#include "QVariableDeclaration.h" #include "QVariableDeclaration.h"
#include "QVariableDefinition.h"
#include "ContractCallDataEncoder.h" #include "ContractCallDataEncoder.h"
#include "CodeModel.h" #include "CodeModel.h"
#include "ClientModel.h" #include "ClientModel.h"
@ -83,7 +85,7 @@ ClientModel::ClientModel(AppContext* _context):
qRegisterMetaType<TransactionLogEntry*>("TransactionLogEntry"); qRegisterMetaType<TransactionLogEntry*>("TransactionLogEntry");
connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection);
m_client.reset(new MixClient()); 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(), std::vector<dev::KeyPair> { m_client->userAccount() }, 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);
@ -111,8 +113,25 @@ QString ClientModel::apiCall(QString const& _message)
void ClientModel::mine() void ClientModel::mine()
{ {
m_client->mine(); if (m_running)
newBlock(); BOOST_THROW_EXCEPTION(ExecutionStateException());
m_running = true;
emit runStarted();
emit runStateChanged();
QtConcurrent::run([=]()
{
try
{
m_client->mine();
newBlock();
}
catch (...)
{
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
m_running = false;
});
} }
QString ClientModel::contractAddress() const QString ClientModel::contractAddress() const
@ -145,7 +164,7 @@ void ClientModel::setupState(QVariantMap _state)
TransactionSettings transactionSettings(functionId, transaction.value("url").toString()); TransactionSettings transactionSettings(functionId, transaction.value("url").toString());
transactionSettings.gasPrice = 10000000000000; transactionSettings.gasPrice = 10000000000000;
transactionSettings.gas = 125000; transactionSettings.gas = 125000;
transactionSettings.value = 100; transactionSettings.value = 0;
transactionSequence.push_back(transactionSettings); transactionSequence.push_back(transactionSettings);
} }
else else
@ -242,11 +261,13 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
} }
catch(boost::exception const&) catch(boost::exception const&)
{ {
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information())); emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
} }
catch(std::exception const& e) catch(std::exception const& e)
{ {
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(e.what()); emit runFailed(e.what());
} }
m_running = false; m_running = false;
@ -256,7 +277,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
void ClientModel::showDebugger() void ClientModel::showDebugger()
{ {
ExecutionResult const& last = m_client->record().back().transactions.back(); ExecutionResult const& last = m_client->lastExecution();
showDebuggerForTransaction(last); showDebuggerForTransaction(last);
} }
@ -289,7 +310,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
void ClientModel::debugTransaction(unsigned _block, unsigned _index) void ClientModel::debugTransaction(unsigned _block, unsigned _index)
{ {
auto const& t = m_client->record().at(_block).transactions.at(_index); auto const& t = m_client->execution(_block, _index);
showDebuggerForTransaction(t); showDebuggerForTransaction(t);
} }
@ -320,9 +341,9 @@ void ClientModel::onStateReset()
void ClientModel::onNewTransaction() void ClientModel::onNewTransaction()
{ {
unsigned block = m_client->number(); unsigned block = m_client->number() + 1;
unsigned index = m_client->record().back().transactions.size() - 1; unsigned index = m_client->pendingExecutions().size() - 1;
ExecutionResult const& tr = m_client->record().back().transactions.back(); ExecutionResult const& tr = m_client->lastExecution();
QString address = QString::fromStdString(toJS(tr.address)); QString address = QString::fromStdString(toJS(tr.address));
QString value = QString::fromStdString(dev::toString(tr.value)); QString value = QString::fromStdString(dev::toString(tr.value));
QString contract = address; QString contract = address;

5
mix/ClientModel.h

@ -26,8 +26,7 @@
#include <atomic> #include <atomic>
#include <map> #include <map>
#include <QString> #include <QString>
#include "MixClient.h" #include "MachineStates.h"
#include "QVariableDefinition.h"
namespace dev namespace dev
{ {
@ -39,6 +38,8 @@ class Web3Server;
class RpcConnector; class RpcConnector;
class QEther; class QEther;
class QDebugData; class QDebugData;
class MixClient;
class QVariableDefinition;
/// Backend transaction config class /// Backend transaction config class
struct TransactionSettings struct TransactionSettings

2
mix/ContractCallDataEncoder.cpp

@ -23,7 +23,7 @@
#include <QDebug> #include <QDebug>
#include <QMap> #include <QMap>
#include <QStringList> #include <QStringList>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include "QVariableDeclaration.h" #include "QVariableDeclaration.h"
#include "QVariableDefinition.h" #include "QVariableDefinition.h"

2
mix/DebuggingStateWrapper.cpp

@ -26,7 +26,7 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QVariantList> #include <QVariantList>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>

222
mix/MixClient.cpp

@ -23,7 +23,7 @@
#include <vector> #include <vector>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include <libethereum/Executive.h> #include <libethereum/Executive.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
@ -36,35 +36,50 @@ using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::mix; using namespace dev::mix;
const Secret c_stdSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const Secret c_userAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074");
MixClient::MixClient(): MixClient::MixClient(std::string const& _dbPath):
m_userAccount(c_stdSecret) m_userAccount(c_userAccountSecret), m_bc(_dbPath, true), m_dbPath(_dbPath), m_minigThreads(0)
{
//TODO: put this into genesis block somehow
//resetState(10000000 * ether);
}
MixClient::~MixClient()
{ {
resetState(10000000 * ether);
} }
void MixClient::resetState(u256 _balance) void MixClient::resetState(u256 _balance)
{ {
WriteGuard l(x_state); (void) _balance;
Guard fl(m_filterLock); {
m_filters.clear(); WriteGuard l(x_state);
m_watches.clear(); Guard fl(m_filterLock);
m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Genesis); m_filters.clear();
m_state.addBalance(m_userAccount.address(), _balance); m_watches.clear();
Block genesis; m_bc.reopen(m_dbPath, true);
genesis.state = m_state; m_state = eth::State();
Block open; m_stateDB = OverlayDB();
m_blocks = Blocks { genesis, open }; //last block contains a list of pending transactions to be finalized m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::CanonGenesis);
// m_lastHashes.clear(); m_state.sync(m_bc);
// m_lastHashes.resize(256); m_startState = m_state;
// m_lastHashes[0] = genesis.hash; m_pendingExecutions.clear();
}
mine();
} }
void MixClient::executeTransaction(Transaction const& _t, State& _state) void MixClient::executeTransaction(Transaction const& _t, State& _state)
{ {
bytes rlp = _t.rlp(); bytes rlp = _t.rlp();
Executive execution(_state, LastHashes(), 0);
// do debugging run first
LastHashes lastHashes(256);
lastHashes[0] = m_bc.numberHash(m_bc.number());
for (unsigned i = 1; i < 256; ++i)
lastHashes[i] = lastHashes[i - 1] ? m_bc.details(lastHashes[i - 1]).parent : h256();
State execState = _state;
Executive execution(execState, lastHashes, 0);
execution.setup(&rlp); execution.setup(&rlp);
std::vector<MachineState> machineStates; std::vector<MachineState> machineStates;
std::vector<unsigned> levels; std::vector<unsigned> levels;
@ -130,21 +145,25 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
d.value = _t.value(); d.value = _t.value();
if (_t.isCreation()) if (_t.isCreation())
d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce()))); d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce())));
d.receipt = TransactionReceipt(m_state.rootHash(), execution.gasUsed(), execution.logs()); //TODO: track gas usage d.receipt = TransactionReceipt(execState.rootHash(), execution.gasUsed(), execution.logs()); //TODO: track gas usage
m_blocks.back().transactions.emplace_back(d); m_pendingExecutions.emplace_back(std::move(d));
// execute on a state
_state.execute(lastHashes, rlp, nullptr, true);
// collect watches
h256Set changed; h256Set changed;
Guard l(m_filterLock); Guard l(m_filterLock);
for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters) for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() > m_blocks.size() - 1) if ((unsigned)i.second.filter.latest() > m_bc.number())
{ {
// acceptable number. // acceptable number.
auto m = i.second.filter.matches(d.receipt); auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1));
if (m.size()) if (m.size())
{ {
// filter catches them // filter catches them
for (LogEntry const& l: m) for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, m_blocks.size())); i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1));
changed.insert(i.first); changed.insert(i.first);
} }
} }
@ -152,44 +171,56 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state)
noteChanged(changed); noteChanged(changed);
} }
void MixClient::validateBlock(int _block) const
{
if (_block != -1 && _block != 0 && (unsigned)_block >= m_blocks.size() - 1)
BOOST_THROW_EXCEPTION(InvalidBlockException() << BlockIndex(_block));
}
void MixClient::mine() void MixClient::mine()
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
Block& block = m_blocks.back(); m_state.commitToMine(m_bc);
m_state.mine(0, true); while (!m_state.mine(100, true).completed) {}
m_state.completeMine(); m_state.completeMine();
m_state.commitToMine(BlockChain()); m_bc.import(m_state.blockData(), m_stateDB);
m_state.cleanup(true); m_state.sync(m_bc);
block.state = m_state; //m_state.cleanup(true);
block.info = m_state.info(); m_startState = m_state;
block.hash = block.info.hash; m_executions.emplace_back(std::move(m_pendingExecutions));
m_blocks.push_back(Block());
h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter };
noteChanged(changed); noteChanged(changed);
} }
State const& MixClient::asOf(int _block) const ExecutionResult const& MixClient::execution(unsigned _block, unsigned _transaction) const
{
if (_block == m_bc.number() + 1)
return m_pendingExecutions.at(_transaction);
return m_executions.at(_block).at(_transaction);
}
ExecutionResult const& MixClient::lastExecution() const
{
if (m_pendingExecutions.size() > 0)
return m_pendingExecutions.back();
return m_executions.back().back();
}
ExecutionResults const& MixClient::pendingExecutions() const
{ {
validateBlock(_block); return m_pendingExecutions;
}
State MixClient::asOf(int _block) const
{
ReadGuard l(x_state);
if (_block == 0) if (_block == 0)
return m_blocks[m_blocks.size() - 2].state;
else if (_block == -1)
return m_state; return m_state;
else if (_block == -1)
return m_startState;
else else
return m_blocks[_block].state; return State(m_stateDB, m_bc, m_bc.numberHash(_block));
} }
void MixClient::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) void MixClient::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret)); u256 n = m_state.transactionsFrom(toAddress(_secret));
_gasPrice = 0; //TODO: remove after fixing setBalance
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret);
executeTransaction(t, m_state); executeTransaction(t, m_state);
} }
@ -198,6 +229,7 @@ Address MixClient::transact(Secret _secret, u256 _endowment, bytes const& _init,
{ {
WriteGuard l(x_state); WriteGuard l(x_state);
u256 n = m_state.transactionsFrom(toAddress(_secret)); u256 n = m_state.transactionsFrom(toAddress(_secret));
_gasPrice = 0; //TODO: remove after fixing setBalance
eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret);
executeTransaction(t, m_state); executeTransaction(t, m_state);
Address address = right160(sha3(rlpList(t.sender(), t.nonce()))); Address address = right160(sha3(rlpList(t.sender(), t.nonce())));
@ -228,36 +260,31 @@ bytes MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _
bytes rlp = t.rlp(); bytes rlp = t.rlp();
WriteGuard lw(x_state); //TODO: lock is required only for last execution state WriteGuard lw(x_state); //TODO: lock is required only for last execution state
executeTransaction(t, temp); executeTransaction(t, temp);
return m_blocks.back().transactions.back().returnValue; return m_pendingExecutions.back().returnValue;
} }
u256 MixClient::balanceAt(Address _a, int _block) const u256 MixClient::balanceAt(Address _a, int _block) const
{ {
ReadGuard l(x_state);
return asOf(_block).balance(_a); return asOf(_block).balance(_a);
} }
u256 MixClient::countAt(Address _a, int _block) const u256 MixClient::countAt(Address _a, int _block) const
{ {
ReadGuard l(x_state);
return asOf(_block).transactionsFrom(_a); return asOf(_block).transactionsFrom(_a);
} }
u256 MixClient::stateAt(Address _a, u256 _l, int _block) const u256 MixClient::stateAt(Address _a, u256 _l, int _block) const
{ {
ReadGuard l(x_state);
return asOf(_block).storage(_a, _l); return asOf(_block).storage(_a, _l);
} }
bytes MixClient::codeAt(Address _a, int _block) const bytes MixClient::codeAt(Address _a, int _block) const
{ {
ReadGuard l(x_state);
return asOf(_block).code(_a); return asOf(_block).code(_a);
} }
std::map<u256, u256> MixClient::storageAt(Address _a, int _block) const std::map<u256, u256> MixClient::storageAt(Address _a, int _block) const
{ {
ReadGuard l(x_state);
return asOf(_block).storage(_a); return asOf(_block).storage(_a);
} }
@ -274,23 +301,40 @@ eth::LocalisedLogEntries MixClient::logs(unsigned _watchId) const
eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const
{ {
LocalisedLogEntries ret; LocalisedLogEntries ret;
unsigned lastBlock = m_blocks.size() - 1; //last block contains pending transactions unsigned lastBlock = m_bc.number();
unsigned block = std::min<unsigned>(lastBlock, (unsigned)_f.latest()); unsigned block = std::min<unsigned>(lastBlock, (unsigned)_f.latest());
unsigned end = std::min(lastBlock, std::min(block, (unsigned)_f.earliest())); unsigned end = std::min(lastBlock, std::min(block, (unsigned)_f.earliest()));
for (; ret.size() != _f.max() && block != end; block--) unsigned skip = _f.skip();
// Pending transactions
if (block > m_bc.number())
{ {
bool pendingBlock = (block == lastBlock); ReadGuard l(x_state);
if (pendingBlock || _f.matches(m_blocks[block].info.logBloom)) for (unsigned i = 0; i < m_state.pending().size(); ++i)
for (ExecutionResult const& t: m_blocks[block].transactions) {
if (pendingBlock || _f.matches(t.receipt.bloom())) // Might have a transaction that contains a matching log.
TransactionReceipt const& tr = m_state.receipt(i);
LogEntries logEntries = _f.matches(tr);
for (unsigned entry = 0; entry < logEntries.size() && ret.size() != _f.max(); ++entry)
ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block));
skip -= std::min(skip, static_cast<unsigned>(logEntries.size()));
}
block = m_bc.number();
}
// The rest
auto h = m_bc.numberHash(block);
for (; ret.size() != block && block != end; block--)
{
if (_f.matches(m_bc.info(h).logBloom))
for (TransactionReceipt receipt: m_bc.receipts(h).receipts)
if (_f.matches(receipt.bloom()))
{ {
LogEntries logEntries = _f.matches(t.receipt); LogEntries logEntries = _f.matches(receipt);
if (logEntries.size()) for (unsigned entry = skip; entry < logEntries.size() && ret.size() != _f.max(); ++entry)
{ ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block));
for (unsigned entry = _f.skip(); entry < logEntries.size() && ret.size() != _f.max(); ++entry) skip -= std::min(skip, static_cast<unsigned>(logEntries.size()));
ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block));
}
} }
h = m_bc.details(h).parent;
} }
return ret; return ret;
} }
@ -372,66 +416,65 @@ LocalisedLogEntries MixClient::checkWatch(unsigned _watchId)
h256 MixClient::hashFromNumber(unsigned _number) const h256 MixClient::hashFromNumber(unsigned _number) const
{ {
validateBlock(_number); return m_bc.numberHash(_number);
return m_blocks[_number].hash;
} }
eth::BlockInfo MixClient::blockInfo(h256 _hash) const eth::BlockInfo MixClient::blockInfo(h256 _hash) const
{ {
(void)_hash; return BlockInfo(m_bc.block(_hash));
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::blockInfo"));
} }
eth::BlockDetails MixClient::blockDetails(h256 _hash) const eth::BlockDetails MixClient::blockDetails(h256 _hash) const
{ {
(void)_hash; return m_bc.details(_hash);
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::blockDetails"));
} }
eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const
{ {
(void)_blockHash; auto bl = m_bc.block(_blockHash);
(void)_i; RLP b(bl);
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::transaction")); if (_i < b[1].itemCount())
return Transaction(b[1][_i].data(), CheckSignature::Range);
else
return Transaction();
} }
eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const
{ {
(void)_blockHash; auto bl = m_bc.block(_blockHash);
(void)_i; RLP b(bl);
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::uncle")); if (_i < b[2].itemCount())
return BlockInfo::fromHeader(b[2][_i].data());
else
return BlockInfo();
} }
unsigned MixClient::number() const unsigned MixClient::number() const
{ {
return m_blocks.size() - 1; return m_bc.number();
} }
eth::Transactions MixClient::pending() const eth::Transactions MixClient::pending() const
{ {
return eth::Transactions(); return m_state.pending();
} }
eth::StateDiff MixClient::diff(unsigned _txi, h256 _block) const eth::StateDiff MixClient::diff(unsigned _txi, h256 _block) const
{ {
(void)_txi; State st(m_stateDB, m_bc, _block);
(void)_block; return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::diff"));
} }
eth::StateDiff MixClient::diff(unsigned _txi, int _block) const eth::StateDiff MixClient::diff(unsigned _txi, int _block) const
{ {
(void)_txi; State st = asOf(_block);
(void)_block; return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::diff"));
} }
Addresses MixClient::addresses(int _block) const Addresses MixClient::addresses(int _block) const
{ {
validateBlock(_block);
ReadGuard l(x_state);
Addresses ret; Addresses ret;
for (auto const& i: m_state.addresses()) for (auto const& i: asOf(_block).addresses())
ret.push_back(i.first); ret.push_back(i.first);
return ret; return ret;
} }
@ -456,23 +499,22 @@ Address MixClient::address() const
void MixClient::setMiningThreads(unsigned _threads) void MixClient::setMiningThreads(unsigned _threads)
{ {
(void)_threads; m_minigThreads = _threads;
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::setMiningThreads"));
} }
unsigned MixClient::miningThreads() const unsigned MixClient::miningThreads() const
{ {
return 0; return m_minigThreads;
} }
void MixClient::startMining() void MixClient::startMining()
{ {
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::startMining")); //no-op
} }
void MixClient::stopMining() void MixClient::stopMining()
{ {
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::stopMining")); //no-op
} }
bool MixClient::isMining() bool MixClient::isMining()

30
mix/MixClient.h

@ -24,8 +24,10 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <string>
#include <libethereum/Interface.h> #include <libethereum/Interface.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/CanonBlockChain.h>
#include "MachineStates.h" #include "MachineStates.h"
namespace dev namespace dev
@ -33,26 +35,18 @@ namespace dev
namespace mix namespace mix
{ {
struct Block
{
ExecutionResults transactions;
h256 hash;
dev::eth::State state;
dev::eth::BlockInfo info;
};
using Blocks = std::vector<Block>;
class MixClient: public dev::eth::Interface class MixClient: public dev::eth::Interface
{ {
public: public:
MixClient(); MixClient(std::string const& _dbPath);
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(u256 _balance);
KeyPair const& userAccount() const { return m_userAccount; } KeyPair const& userAccount() const { return m_userAccount; }
void mine(); void mine();
Blocks const& record() const { return m_blocks; } ExecutionResult const& execution(unsigned _block, unsigned _transaction) const;
ExecutionResult const& lastExecution() const;
ExecutionResults const& pendingExecutions() const;
//dev::eth::Interface //dev::eth::Interface
void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override; void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override;
@ -94,18 +88,22 @@ public:
private: private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state); void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);
void validateBlock(int _block) const;
void noteChanged(h256Set const& _filters); void noteChanged(h256Set const& _filters);
dev::eth::State const& asOf(int _block) const; dev::eth::State asOf(int _block) const;
KeyPair m_userAccount; KeyPair m_userAccount;
eth::State m_state; eth::State m_state;
eth::State m_startState;
OverlayDB m_stateDB; OverlayDB m_stateDB;
eth::CanonBlockChain m_bc;
mutable boost::shared_mutex x_state; mutable boost::shared_mutex x_state;
mutable std::mutex m_filterLock; mutable std::mutex m_filterLock;
std::map<h256, dev::eth::InstalledFilter> m_filters; std::map<h256, dev::eth::InstalledFilter> m_filters;
std::map<unsigned, dev::eth::ClientWatch> m_watches; std::map<unsigned, dev::eth::ClientWatch> m_watches;
Blocks m_blocks; std::vector<ExecutionResults> m_executions;
ExecutionResults m_pendingExecutions;
std::string m_dbPath;
unsigned m_minigThreads;
}; };
} }

2
mix/QBigInt.cpp

@ -21,7 +21,7 @@
#include <boost/variant/multivisitors.hpp> #include <boost/variant/multivisitors.hpp>
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include "QBigInt.h" #include "QBigInt.h"
using namespace dev; using namespace dev;

2
mix/QBigInt.h

@ -26,7 +26,7 @@
#include "boost/variant/multivisitors.hpp" #include "boost/variant/multivisitors.hpp"
#include <QObject> #include <QObject>
#include <QQmlEngine> #include <QQmlEngine>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
using namespace dev; using namespace dev;

2
mix/QVariableDefinition.cpp

@ -20,7 +20,7 @@
*/ */
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include "QVariableDefinition.h" #include "QVariableDefinition.h"
using namespace dev::mix; using namespace dev::mix;

3
mix/qml/MainContent.qml

@ -59,8 +59,7 @@ Rectangle {
} }
function hideRightView() { function hideRightView() {
if (rightView.visible) rightView.visible = false;
rightView.hide();
} }
function toggleWebPreview() { function toggleWebPreview() {

15
mix/qml/WebCodeEditor.qml

@ -4,6 +4,7 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1 import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0 import CodeEditorExtensionManager 1.0
import QtWebEngine 1.0 import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
Item { Item {
signal editorTextChanged signal editorTextChanged
@ -29,6 +30,18 @@ Item {
return currentText; return currentText;
} }
function syncClipboard() {
if (Qt.platform.os == "osx") {
var text = appContext.clipboard;
editorBrowser.runJavaScript("setClipboardBase64(\"" + Qt.btoa(text) + "\")");
}
}
Connections {
target: appContext
onClipboardChanged: syncClipboard()
}
anchors.top: parent.top anchors.top: parent.top
id: codeEditorView id: codeEditorView
anchors.fill: parent anchors.fill: parent
@ -36,6 +49,7 @@ Item {
id: editorBrowser id: editorBrowser
url: "qrc:///qml/html/codeeditor.html" url: "qrc:///qml/html/codeeditor.html"
anchors.fill: parent anchors.fill: parent
experimental.settings.javascriptCanAccessClipboard: true
onJavaScriptConsoleMessage: { onJavaScriptConsoleMessage: {
console.log("editor: " + sourceID + ":" + lineNumber + ":" + message); console.log("editor: " + sourceID + ":" + lineNumber + ":" + message);
} }
@ -47,6 +61,7 @@ Item {
setText(currentText, currentMode); setText(currentText, currentMode);
runJavaScript("getTextChanged()", function(result) { }); runJavaScript("getTextChanged()", function(result) { });
pollTimer.running = true; pollTimer.running = true;
syncClipboard();
} }
} }

2
mix/qml/html/cm/codemirror.js

@ -29,7 +29,7 @@
var ie = ie_upto10 || ie_11up; var ie = ie_upto10 || ie_11up;
var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
var webkit = /WebKit\//.test(navigator.userAgent); var webkit = /WebKit\//.test(navigator.userAgent);
var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); var qtwebkit = true;
var chrome = /Chrome\//.test(navigator.userAgent); var chrome = /Chrome\//.test(navigator.userAgent);
var presto = /Opera\//.test(navigator.userAgent); var presto = /Opera\//.test(navigator.userAgent);
var safari = /Apple Computer/.test(navigator.vendor); var safari = /Apple Computer/.test(navigator.vendor);

20
mix/qml/html/codeeditor.js

@ -6,6 +6,7 @@ var editor = CodeMirror(document.body, {
autofocus: true, autofocus: true,
}); });
editor.setOption("theme", "solarized dark"); editor.setOption("theme", "solarized dark");
editor.setOption("indentUnit", 4); editor.setOption("indentUnit", 4);
editor.setOption("indentWithTabs", true); editor.setOption("indentWithTabs", true);
@ -18,11 +19,24 @@ editor.on("change", function(eMirror, object) {
}); });
var mac = /Mac/.test(navigator.platform);
if (mac === true) {
editor.setOption("extraKeys", {
"Cmd-V": function(cm) {
cm.replaceSelection(clipboard);
},
"Cmd-X": function(cm) {
window.document.execCommand("cut");
},
"Cmd-C": function(cm) {
window.document.execCommand("copy");
}});
}
getTextChanged = function() { getTextChanged = function() {
return editor.changeRegistered; return editor.changeRegistered;
}; };
getText = function() { getText = function() {
editor.changeRegistered = false; editor.changeRegistered = false;
return editor.getValue(); return editor.getValue();
@ -42,3 +56,7 @@ setText = function(text) {
setMode = function(mode) { setMode = function(mode) {
this.editor.setOption("mode", mode); this.editor.setOption("mode", mode);
}; };
setClipboardBase64 = function(text) {
clipboard = window.atob(text);
};

1
mix/qml/main.qml

@ -4,6 +4,7 @@ import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Window 2.1 import QtQuick.Window 2.1
import QtQuick.PrivateWidgets 1.1
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import org.ethereum.qml.QEther 1.0 import org.ethereum.qml.QEther 1.0

5
pullSerpent.sh

@ -2,10 +2,11 @@
opwd="$PWD" opwd="$PWD"
cd ../serpent cd ../serpent
git stash
git pull git pull
git stash pop
cp bignum.* compiler.* funcs.* lllparser.* opcodes.h parser.* rewriter.* tokenize.* util.* ../cpp-ethereum/libserpent/ cp bignum.* compiler.* funcs.* lllparser.* opcodes.h parser.* rewriter.* tokenize.* util.* ../cpp-ethereum/libserpent/
cp cmdline.* "$opwd/sc/" cp cmdline.* "$opwd/sc/"
cp pyserpent.* "$opwd/libpyserpent/"
cd "$opwd" cd "$opwd"
perl -i -p -e 's:include "funcs.h":include <libserpent/funcs.h>:gc' sc/* libpyserpent/* perl -i -p -e 's:include "funcs.h":include <libserpent/funcs.h>:gc' sc/*

5
sc/cmdline.cpp

@ -68,7 +68,7 @@ int main(int argv, char** argc) {
std::cout << binToHex(compileLLL(parseLLL(input, true))) << "\n"; std::cout << binToHex(compileLLL(parseLLL(input, true))) << "\n";
} }
else if (command == "dereference") { else if (command == "dereference") {
std::cout << printAST(dereference(parseLLL(input, true)), haveSec) <<"\n"; std::cout << printTokens(dereference(parseLLL(input, true))) <<"\n";
} }
else if (command == "pretty_assemble") { else if (command == "pretty_assemble") {
std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n"; std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n";
@ -88,9 +88,6 @@ int main(int argv, char** argc) {
else if (command == "serialize") { else if (command == "serialize") {
std::cout << binToHex(serialize(tokenize(input, Metadata(), false))) << "\n"; std::cout << binToHex(serialize(tokenize(input, Metadata(), false))) << "\n";
} }
else if (command == "flatten") {
std::cout << printTokens(flatten(parseLLL(input, true))) << "\n";
}
else if (command == "deserialize") { else if (command == "deserialize") {
std::cout << printTokens(deserialize(hexToBin(input))) << "\n"; std::cout << printTokens(deserialize(hexToBin(input))) << "\n";
} }

55
test/SolidityEndToEndTest.cpp

@ -92,6 +92,26 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes()); BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()) == bytes());
} }
BOOST_AUTO_TEST_CASE(named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(disorder_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(while_loop) BOOST_AUTO_TEST_CASE(while_loop)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -885,7 +905,7 @@ BOOST_AUTO_TEST_CASE(constructor)
BOOST_AUTO_TEST_CASE(simple_accessor) BOOST_AUTO_TEST_CASE(simple_accessor)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" uint256 data;\n" " uint256 public data;\n"
" function test() {\n" " function test() {\n"
" data = 8;\n" " data = 8;\n"
" }\n" " }\n"
@ -897,10 +917,10 @@ BOOST_AUTO_TEST_CASE(simple_accessor)
BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
" uint256 data;\n" " uint256 public data;\n"
" string6 name;\n" " string6 public name;\n"
" hash a_hash;\n" " hash public a_hash;\n"
" address an_address;\n" " address public an_address;\n"
" function test() {\n" " function test() {\n"
" data = 8;\n" " data = 8;\n"
" name = \"Celina\";\n" " name = \"Celina\";\n"
@ -908,7 +928,6 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
" an_address = address(0x1337);\n" " an_address = address(0x1337);\n"
" super_secret_data = 42;\n" " super_secret_data = 42;\n"
" }\n" " }\n"
" private:"
" uint256 super_secret_data;" " uint256 super_secret_data;"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
@ -919,6 +938,27 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); BOOST_CHECK(callContractFunction("super_secret_data()") == bytes());
} }
BOOST_AUTO_TEST_CASE(complex_accessors)
{
char const* sourceCode = "contract test {\n"
" mapping(uint256 => string4) public to_string_map;\n"
" mapping(uint256 => bool) public to_bool_map;\n"
" mapping(uint256 => uint256) public to_uint_map;\n"
" mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map;\n"
" function test() {\n"
" to_string_map[42] = \"24\";\n"
" to_bool_map[42] = false;\n"
" to_uint_map[42] = 12;\n"
" to_multiple_map[42][23] = 31;\n"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24"));
BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false));
BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12));
BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31));
}
BOOST_AUTO_TEST_CASE(balance) BOOST_AUTO_TEST_CASE(balance)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"
@ -1490,8 +1530,7 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor)
setName("abc"); setName("abc");
} }
function getName() returns (string3 ret) { return name; } function getName() returns (string3 ret) { return name; }
private: function setName(string3 _name) private { name = _name; }
function setName(string3 _name) { name = _name; }
})"; })";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc")); BOOST_REQUIRE(callContractFunction("getName()") == encodeArgs("abc"));

134
test/SolidityNameAndTypeResolution.cpp

@ -467,6 +467,24 @@ BOOST_AUTO_TEST_CASE(illegal_override_indirect)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
} }
BOOST_AUTO_TEST_CASE(illegal_override_visibility)
{
char const* text = R"(
contract B { function f() protected {} }
contract C is B { function f() public {} }
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(illegal_override_constness)
{
char const* text = R"(
contract B { function f() constant {} }
contract C is B { function f() {} }
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(complex_inheritance) BOOST_AUTO_TEST_CASE(complex_inheritance)
{ {
char const* text = R"( char const* text = R"(
@ -636,7 +654,9 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
" function fun() {\n" " function fun() {\n"
" uint64(2);\n" " uint64(2);\n"
" }\n" " }\n"
"uint256 foo;\n" "uint256 public foo;\n"
"mapping(uint=>string4) public map;\n"
"mapping(uint=>mapping(uint=>string4)) public multiple_map;\n"
"}\n"; "}\n";
ASTPointer<SourceUnit> source; ASTPointer<SourceUnit> source;
@ -644,10 +664,27 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr); BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
BOOST_REQUIRE(function->hasDeclaration()); BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->getReturnParameterTypeNames(); auto returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
BOOST_CHECK(function->isConstant()); BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
auto params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(params.at(0), "uint256");
returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(params.at(0), "uint256");
BOOST_CHECK_EQUAL(params.at(1), "uint256");
returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant());
} }
BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
@ -668,16 +705,19 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
" function fun() {\n" " function fun() {\n"
" uint64(2);\n" " uint64(2);\n"
" }\n" " }\n"
"private:\n" "uint256 private foo;\n"
"uint256 foo;\n" "uint256 protected bar;\n"
"}\n"; "}\n";
ASTPointer<SourceUnit> source; ASTPointer<SourceUnit> source;
ContractDefinition const* contract; ContractDefinition const* contract;
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text)); BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr); BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); FunctionTypePointer function;
function = retrieveFunctionBySignature(contract, "foo()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
function = retrieveFunctionBySignature(contract, "bar()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a protected variable should not exist");
} }
BOOST_AUTO_TEST_CASE(fallback_function) BOOST_AUTO_TEST_CASE(fallback_function)
@ -780,6 +820,90 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
} }
BOOST_AUTO_TEST_CASE(access_to_default_function_visibility)
{
char const* text = R"(
contract c {
function f() {}
}
contract d {
function g() { c(0).f(); }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(access_to_protected_function)
{
char const* text = R"(
contract c {
function f() protected {}
}
contract d {
function g() { c(0).f(); }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility)
{
char const* text = R"(
contract c {
uint a;
}
contract d {
function g() { c(0).a(); }
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(access_to_protected_state_variable)
{
char const* text = R"(
contract c {
uint public a;
}
contract d {
function g() { c(0).a(); }
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(error_count_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(empty_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1, a: 2}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
{
char const* sourceCode = "contract test {\n"
" function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
" function b() returns (uint r) { r = a({a: 1, c: 2}); }\n"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

49
test/SolidityParser.cpp

@ -124,14 +124,30 @@ BOOST_AUTO_TEST_CASE(single_function_param)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args)
{
char const* text = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({: 1, : 2, : 3}); }\n"
"}\n";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(missing_argument_in_named_args)
{
char const* text = "contract test {\n"
" function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
" function b() returns (uint r) { r = a({a: , b: , c: }); }\n"
"}\n";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_AUTO_TEST_CASE(function_natspec_documentation)
{ {
ASTPointer<ContractDefinition> contract; ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function; ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n" char const* text = "contract test {\n"
" private:\n" " uint256 stateVar;\n"
" uint256 stateVar;\n"
" public:\n"
" /// This is a test function\n" " /// This is a test function\n"
" function functionName(hash hashin) returns (hash hashout) {}\n" " function functionName(hash hashin) returns (hash hashout) {}\n"
"}\n"; "}\n";
@ -162,9 +178,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
ASTPointer<ContractDefinition> contract; ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function; ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n" char const* text = "contract test {\n"
" private:\n"
" uint256 stateVar;\n" " uint256 stateVar;\n"
" public:\n"
" /// This is test function 1\n" " /// This is test function 1\n"
" function functionName1(hash hashin) returns (hash hashout) {}\n" " function functionName1(hash hashin) returns (hash hashout) {}\n"
" /// This is test function 2\n" " /// This is test function 2\n"
@ -621,6 +635,31 @@ BOOST_AUTO_TEST_CASE(event_arguments_indexed)
BOOST_CHECK_NO_THROW(parseText(text)); BOOST_CHECK_NO_THROW(parseText(text));
} }
BOOST_AUTO_TEST_CASE(visibility_specifiers)
{
char const* text = R"(
contract c {
uint private a;
uint protected b;
uint public c;
uint d;
function f() {}
function f_priv() private {}
function f_public() public {}
function f_protected() protected {}
})";
BOOST_CHECK_NO_THROW(parseText(text));
}
BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
{
char const* text = R"(
contract c {
uint private protected a;
})";
BOOST_CHECK_THROW(parseText(text), ParserError);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

5
test/commonjs.cpp

@ -20,7 +20,8 @@
*/ */
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <libdevcore/CommonJS.h> #include <libdevcore/Log.h>
#include <libethcore/CommonJS.h>
BOOST_AUTO_TEST_SUITE(commonjs) BOOST_AUTO_TEST_SUITE(commonjs)
using namespace std; using namespace std;
@ -41,7 +42,7 @@ BOOST_AUTO_TEST_CASE(jsToAddress)
cnote << "Testing jsToPublic..."; cnote << "Testing jsToPublic...";
KeyPair kp = KeyPair::create(); KeyPair kp = KeyPair::create();
string string = toJS(kp.address()); string string = toJS(kp.address());
Address address = dev::jsToAddress(string); Address address = dev::eth::jsToAddress(string);
BOOST_CHECK_EQUAL(kp.address(), address); BOOST_CHECK_EQUAL(kp.address(), address);
} }

2
test/fork.cpp

@ -23,7 +23,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/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

8
test/genesis.cpp

@ -24,7 +24,7 @@
#include <random> #include <random>
#include "JsonSpiritHeaders.h" #include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "TestHelper.h" #include "TestHelper.h"
@ -58,9 +58,9 @@ BOOST_AUTO_TEST_CASE(genesis_tests)
js::mObject o = v.get_obj(); js::mObject o = v.get_obj();
BOOST_CHECK_EQUAL(BlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str())); BOOST_CHECK_EQUAL(CanonBlockChain::genesis().stateRoot, h256(o["genesis_state_root"].get_str()));
BOOST_CHECK_EQUAL(toHex(BlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str()))); BOOST_CHECK_EQUAL(toHex(CanonBlockChain::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str())));
BOOST_CHECK_EQUAL(BlockInfo::headerHash(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str())); BOOST_CHECK_EQUAL(BlockInfo::headerHash(CanonBlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str()));
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

2
test/jsonrpc.cpp

@ -28,7 +28,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h> #include <jsonrpccpp/server/connectors/httpserver.h>

2
test/state.cpp

@ -24,7 +24,7 @@
#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/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>

4
test/stateOriginal.cpp

@ -22,7 +22,7 @@
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libethereum/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
using namespace std; using namespace std;
@ -40,7 +40,7 @@ int stateTest()
Defaults::setDBPath(boost::filesystem::temp_directory_path().string()); Defaults::setDBPath(boost::filesystem::temp_directory_path().string());
OverlayDB stateDB = State::openDB(); OverlayDB stateDB = State::openDB();
BlockChain bc; CanonBlockChain bc;
State s(myMiner.address(), stateDB); State s(myMiner.address(), stateDB);
cout << bc; cout << bc;

2
test/txTest.cpp

@ -23,7 +23,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/BlockChain.h> #include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h> #include <libethereum/EthereumHost.h>
#include "TestHelper.h" #include "TestHelper.h"
using namespace std; using namespace std;

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

Loading…
Cancel
Save