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/util.h>
#include <libdevcrypto/FileSystem.h>
#include <libdevcore/CommonJS.h>
#include <libethcore/CommonJS.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h>
@ -41,7 +41,7 @@
#include <libsolidity/SourceReferenceFormatter.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libethereum/BlockChain.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
@ -136,9 +136,9 @@ Main::Main(QWidget *parent) :
#endif
m_servers.append(QString::fromStdString(Host::pocHost() + ":30303"));
cerr << "State root: " << BlockChain::genesis().stateRoot << endl;
auto block = BlockChain::createGenesisBlock();
cerr << "Block Hash: " << BlockChain::genesis().hash << endl;
cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl;
auto block = CanonBlockChain::createGenesisBlock();
cerr << "Block Hash: " << CanonBlockChain::genesis().hash << endl;
cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << 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"));
}
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
{
@ -1189,7 +1189,10 @@ void Main::timerEvent(QTimerEvent*)
{
auto ls = ethereum()->checkWatch(i.first);
if (ls.size())
{
cnote << "FIRING WATCH" << i.first << ls.size();
i.second(ls);
}
}
}
@ -1202,7 +1205,7 @@ string Main::renderDiff(StateDiff const& _d) const
{
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>";
if (!ad.exist.to())
continue;
@ -1210,7 +1213,7 @@ string Main::renderDiff(StateDiff const& _d) const
if (ad.balance)
{
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>";
}
if (ad.nonce)

4
alethzero/OurWebThreeStubServer.h

@ -20,7 +20,7 @@
*/
#include <QtCore/QObject>
#include <libdevcore/CommonJS.h>
#include <libethcore/CommonJS.h>
#include <libdevcrypto/Common.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
@ -35,7 +35,7 @@ public:
std::vector<dev::KeyPair> const& _accounts, Main* main);
virtual std::string shh_newIdentity() override;
virtual bool authenticate(dev::TransactionSkeleton const& _t);
virtual bool authenticate(dev::eth::TransactionSkeleton const& _t);
signals:
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)
# First have qt5 install plugins and frameworks
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}
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
@ -82,19 +83,11 @@ macro(eth_install_executable EXECUTABLE)
set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app")
endif ()
# TODO check, how fixup_bundle works and if it is required
install(CODE "
include(BundleUtilities)
set(BU_CHMOD_BUNDLE_ITEMS 1)
fixup_bundle(\"${APP_BUNDLE_PATH}\" \"${BUNDLELIBS}\" \"../libqethereum ../libethereum ../secp256k1\")
verify_app(\"${APP_BUNDLE_PATH}\")
" 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")
# copy all dlls to executable directory

3
libdevcore/CMakeLists.txt

@ -26,9 +26,8 @@ else()
endif()
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_CHRONO_LIBRARIES})
if (APPLE)
find_package(Threads REQUIRED)

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using 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.
* This version uses an database backend.
* This version uses a database backend.
* Usage:
* @code
* GenericTrieDB<MyDB> t(&myDB);

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

@ -72,6 +72,31 @@ bytes unpadLeft(bytes _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)
{
unsigned inc = 0;
@ -98,31 +123,6 @@ std::string prettyU256(u256 _n)
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)
{
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
#include <string>
#include <libethereum/Interface.h>
#include "Common.h"
#include "CommonData.h"
#include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include "CommonEth.h"
namespace dev
{
@ -94,16 +96,8 @@ template <unsigned N> boost::multiprecision::number<boost::multiprecision::cpp_i
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 std::string jsToBinary(std::string const& _s)
{
return dev::toString(unpadded(jsToBytes(_s)));
}
inline std::string jsToDecimal(std::string const& _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);
}
}
// 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
{
Address from;
@ -136,3 +153,4 @@ struct TransactionSkeleton
};
}
}

2
libethereum/All.h

@ -1,7 +1,7 @@
#pragma once
#include "Account.h"
#include "BlockChain.h"
#include "CanonBlockChain.h"
#include "Client.h"
#include "Defaults.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;
}
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)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
@ -91,31 +67,11 @@ ldb::Slice dev::eth::toSlice(h256 _h, unsigned _sub)
#endif
}
bytes BlockChain::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();
}
BlockChain::BlockChain(std::string _path, bool _killExisting)
BlockChain::BlockChain(bytes const& _genesisBlock, std::string _path, bool _killExisting)
{
// Initialise with the genesis as the last block on the longest chain.
m_genesisHash = BlockChain::genesis().hash;
m_genesisBlock = BlockChain::createGenesisBlock();
m_genesisBlock = _genesisBlock;
m_genesisHash = sha3(RLP(m_genesisBlock)[0].data());
open(_path, _killExisting);
}
@ -353,7 +309,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db)
}
#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;
// 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
{
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
if (!_from || !_to)
{
return h256s();
@ -386,14 +342,14 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
h256s back;
unsigned fn = details(_from).number;
unsigned tn = details(_to).number;
// cdebug << "treeRoute" << fn << "..." << tn;
// cdebug << "treeRoute" << fn << "..." << tn;
while (fn > tn)
{
if (_pre)
ret.push_back(_from);
_from = details(_from).parent;
fn--;
// cdebug << "from:" << fn << _from.abridged();
// cdebug << "from:" << fn << _from.abridged();
}
while (fn < tn)
{
@ -401,7 +357,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to);
_to = details(_to).parent;
tn--;
// cdebug << "to:" << tn << _to.abridged();
// cdebug << "to:" << tn << _to.abridged();
}
while (_from != _to)
{
@ -415,7 +371,7 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo
back.push_back(_to);
fn--;
tn--;
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
}
if (o_common)
*o_common = _from;

18
libethereum/BlockChain.h

@ -69,8 +69,7 @@ ldb::Slice toSlice(h256 _h, unsigned _sub = 0);
class BlockChain
{
public:
BlockChain(bool _killExisting = false): BlockChain(std::string(), _killExisting) {}
BlockChain(std::string _path, bool _killExisting = false);
BlockChain(bytes const& _genesisBlock, std::string _path, bool _killExisting);
~BlockChain();
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
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.
h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept;
@ -131,13 +130,6 @@ public:
/// togther with all their quoted uncles.
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
* 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);
if (s.empty())
{
// cout << "Not found in DB: " << _h << endl;
// cout << "Not found in DB: " << _h << endl;
return _n;
}
@ -208,10 +200,6 @@ private:
ldb::WriteOptions m_writeOptions;
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);

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

6
libethereum/Client.h

@ -34,7 +34,7 @@
#include <libdevcore/Worker.h>
#include <libevm/FeeStructure.h>
#include <libp2p/Common.h>
#include "BlockChain.h"
#include "CanonBlockChain.h"
#include "TransactionQueue.h"
#include "State.h"
#include "CommonNet.h"
@ -228,7 +228,7 @@ public:
/// Get the object representing the current state of Ethereum.
dev::eth::State postState() const { ReadGuard l(x_stateDB); return m_postMine; }
/// Get the object representing the current canonical blockchain.
BlockChain const& blockChain() const { return m_bc; }
CanonBlockChain const& blockChain() const { return m_bc; }
// Mining stuff:
@ -308,7 +308,7 @@ private:
State asOf(unsigned _h) const;
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.
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::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
{
_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 eth
{
class LogFilter;
}
/// Simple stream output for the StateDiff.
std::ostream& operator<<(std::ostream& _out, dev::eth::LogFilter const& _s);
namespace eth
{
@ -56,14 +65,17 @@ public:
LogFilter withEarliest(int _e) { m_earliest = _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:
AddressSet m_addresses;
std::array<h256Set, 4> m_topics;
int m_earliest = 0;
int m_latest = -1;
unsigned m_max;
unsigned m_skip;
unsigned m_max = 10;
unsigned m_skip = 0;
};
}
}

13
libethereum/State.cpp

@ -35,6 +35,7 @@
#include "ExtVM.h"
#include "Executive.h"
#include "CachedAddressState.h"
#include "CanonBlockChain.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -74,18 +75,16 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs):
paranoia("beginning of normal construction.", true);
if (_bs == BaseState::Genesis)
if (_bs == BaseState::CanonGenesis)
{
dev::eth::commit(genesisState(), m_db, m_state);
m_db.commit();
paranoia("after DB commit of normal construction.", true);
m_previousBlock = BlockChain::genesis();
m_previousBlock = CanonBlockChain::genesis();
}
else
{
m_previousBlock.setEmpty();
}
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.)
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.
bi.populate(_bc.block(bi.parentHash)); // move to parent.
@ -698,7 +697,7 @@ void State::commitToMine(BlockChain const& _bc)
RLPStream unclesData;
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.
// cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl;
@ -800,7 +799,7 @@ void State::completeMine()
ret.appendRaw(m_currentTxs);
ret.appendRaw(m_currentUncles);
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() << ")";
// 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 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.
@ -68,7 +68,7 @@ class State
public:
/// 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.
State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash);

2
libjsqrc/ethereumjs/bower.json

@ -1,7 +1,7 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.11",
"version": "0.0.13",
"description": "Ethereum Compatible JavaScript API",
"main": ["./dist/ethereum.js", "./dist/ethereum.min.js"],
"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.
@ -238,9 +238,32 @@ if ("build" !== 'build') {/*
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 = {
ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
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) {
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', {
get: function() {
@ -386,8 +414,12 @@ var addEventsToContract = function (contract, desc, address) {
var impl = function () {
var params = Array.prototype.slice.call(arguments);
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);
o._onWatchEventResult = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o);
};
@ -455,7 +487,7 @@ var contract = function (address, desc) {
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.
@ -481,6 +513,16 @@ module.exports = contract;
var abi = require('./abi');
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 index = utils.findIndex(inputs, function (input) {
return input.name === name;
@ -496,7 +538,7 @@ var inputWithName = function (inputs, name) {
var indexedParamsToTopics = function (event, indexed) {
// sort keys?
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];
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'
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.
@ -565,6 +663,8 @@ var Filter = function(options, impl) {
if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead');
}
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties
options = {
@ -583,7 +683,7 @@ var Filter = function(options, impl) {
this.callbacks = [];
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*
@ -603,7 +703,8 @@ Filter.prototype.changed = function(callback) {
Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) {
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;
},{"./web3":12}],6:[function(require,module,exports){
},{"./web3":13}],6:[function(require,module,exports){
/*
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.
@ -815,40 +916,16 @@ var HttpSyncProvider = function (host) {
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) {
var data = formatJsonRpcObject(payload);
//var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(data));
request.send(JSON.stringify(payload));
// check request.status
return request.responseText;
var result = request.responseText;
return JSON.parse(result);
};
module.exports = HttpSyncProvider;
@ -871,6 +948,73 @@ module.exports = HttpSyncProvider;
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
};
},{}],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
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
@ -880,7 +1024,9 @@ module.exports = HttpSyncProvider;
* @date 2014
*/
var web3 = require('./web3'); // jshint ignore:line
var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
/**
* Provider manager object prototype
@ -894,25 +1040,35 @@ var web3 = require('./web3'); // jshint ignore:line
var ProviderManager = function() {
this.polls = [];
this.provider = undefined;
this.id = 1;
var self = this;
var poll = function () {
if (self.provider) {
self.polls.forEach(function (data) {
data.data._id = self.id;
self.id++;
var result = self.provider.send(data.data);
result = JSON.parse(result);
var pollsBatch = self.polls.map(function (data) {
return data.data;
});
var payload = jsonrpc.toBatchPayload(pollsBatch);
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
if (result.error || !(result.result instanceof Array) || result.result.length === 0) {
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result.result);
data.callback(result);
});
}
setTimeout(poll, 1000);
};
@ -920,22 +1076,19 @@ var ProviderManager = function() {
};
/// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) {
data.args = data.args || [];
data._id = this.id++;
var payload = jsonrpc.toPayload(data.method, data.params);
if (this.provider === undefined) {
console.error('provider is not set');
return null;
}
//TODO: handle error here?
var result = this.provider.send(data);
result = JSON.parse(result);
var result = this.provider.send(payload);
if (result.error) {
console.log(result.error);
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}
@ -966,7 +1119,7 @@ ProviderManager.prototype.stopPolling = function (pollId) {
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.
@ -994,13 +1147,14 @@ var QtSyncProvider = function () {
};
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;
},{}],10:[function(require,module,exports){
},{}],11:[function(require,module,exports){
/*
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.
@ -1104,6 +1258,8 @@ module.exports = {
* @date 2015
*/
var c = require('./const');
/// Finds first index of array element matching pattern
/// @param array
/// @param callback pattern
@ -1166,7 +1322,7 @@ var extractDisplayName = function (name) {
var extractTypeName = function (name) {
/// TODO: make it invulnerable
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
@ -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 = {
findIndex: findIndex,
toAscii: toAscii,
@ -1192,11 +1374,12 @@ module.exports = {
extractDisplayName: extractDisplayName,
extractTypeName: extractTypeName,
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.
@ -1228,28 +1411,6 @@ if ("build" !== 'build') {/*
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
var web3Methods = function () {
return [
@ -1357,8 +1518,8 @@ var setupMethods = function (obj, methods) {
var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({
call: call,
args: args
method: call,
params: args
});
};
});
@ -1371,15 +1532,15 @@ var setupProperties = function (obj, properties) {
var proto = {};
proto.get = function () {
return web3.provider.send({
call: property.getter
method: property.getter
});
};
if (property.setter) {
proto.set = function (val) {
return web3.provider.send({
call: property.setter,
args: [val]
method: property.setter,
params: [val]
});
};
}
@ -1412,29 +1573,7 @@ var web3 = {
},
/// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int
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];
},
toEth: utils.toEth,
/// eth object prototype
eth: {
@ -1470,11 +1609,6 @@ var web3 = {
return new web3.filter(filter, shhWatch);
}
},
/// @returns true if provider is installed
haveProvider: function() {
return !!web3.provider.provider;
}
};
/// setups all api methods
@ -1497,14 +1631,13 @@ var shhWatch = {
setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) {
//provider.onmessage = messageHandler; // there will be no async calls, to remove
web3.provider.set(provider);
};
module.exports = web3;
},{"./utils":11}],"web3":[function(require,module,exports){
},{"./utils":12}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3');
var ProviderManager = require('./lib/providermanager');
web3.provider = new ProviderManager();
@ -1517,7 +1650,7 @@ web3.abi = require('./lib/abi');
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

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 ETH_UNITS = [
'wei',
'Kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'ether',
'grand',
'Mether',
'Gether',
'Tether',
'Pether',
'Eether',
'Zether',
'Yether',
'Nether',
'Dether',
'Vether',
'Uether'
];
module.exports = {
ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
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) {
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', {
get: function() {
@ -138,8 +143,12 @@ var addEventsToContract = function (contract, desc, address) {
var impl = function () {
var params = Array.prototype.slice.call(arguments);
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);
o._onWatchEventResult = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.watch(o);
};

72
libjsqrc/ethereumjs/lib/event.js

@ -23,6 +23,16 @@
var abi = require('./abi');
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 index = utils.findIndex(inputs, function (input) {
return input.name === name;
@ -38,7 +48,7 @@ var inputWithName = function (inputs, name) {
var indexedParamsToTopics = function (event, indexed) {
// sort keys?
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];
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'
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) {
console.warn('"topics" is deprecated, use "topic" instead');
}
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties
options = {
@ -54,7 +56,7 @@ var Filter = function(options, impl) {
this.callbacks = [];
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*
@ -74,7 +76,8 @@ Filter.prototype.changed = function(callback) {
Filter.prototype.trigger = function(messages) {
for (var i = 0; i < this.callbacks.length; i++) {
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';
};
/// 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) {
var data = formatJsonRpcObject(payload);
//var data = formatJsonRpcObject(payload);
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(data));
request.send(JSON.stringify(payload));
// check request.status
return request.responseText;
var result = request.responseText;
return JSON.parse(result);
};
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
*/
var web3 = require('./web3'); // jshint ignore:line
var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
/**
* Provider manager object prototype
@ -37,25 +39,35 @@ var web3 = require('./web3'); // jshint ignore:line
var ProviderManager = function() {
this.polls = [];
this.provider = undefined;
this.id = 1;
var self = this;
var poll = function () {
if (self.provider) {
self.polls.forEach(function (data) {
data.data._id = self.id;
self.id++;
var result = self.provider.send(data.data);
result = JSON.parse(result);
var pollsBatch = self.polls.map(function (data) {
return data.data;
});
var payload = jsonrpc.toBatchPayload(pollsBatch);
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
if (result.error || !(result.result instanceof Array) || result.result.length === 0) {
if (!(result instanceof Array) || result.length === 0) {
return;
}
data.callback(result.result);
data.callback(result);
});
}
setTimeout(poll, 1000);
};
@ -63,22 +75,19 @@ var ProviderManager = function() {
};
/// sends outgoing requests
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) {
data.args = data.args || [];
data._id = this.id++;
var payload = jsonrpc.toPayload(data.method, data.params);
if (this.provider === undefined) {
console.error('provider is not set');
return null;
}
//TODO: handle error here?
var result = this.provider.send(data);
result = JSON.parse(result);
var result = this.provider.send(payload);
if (result.error) {
console.log(result.error);
if (!jsonrpc.isValidResponse(result)) {
console.log(result);
return null;
}

3
libjsqrc/ethereumjs/lib/qtsync.js

@ -25,7 +25,8 @@ var QtSyncProvider = function () {
};
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;

33
libjsqrc/ethereumjs/lib/utils.js

@ -20,6 +20,8 @@
* @date 2015
*/
var c = require('./const');
/// Finds first index of array element matching pattern
/// @param array
/// @param callback pattern
@ -82,7 +84,7 @@ var extractDisplayName = function (name) {
var extractTypeName = function (name) {
/// TODO: make it invulnerable
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
@ -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 = {
findIndex: findIndex,
toAscii: toAscii,
@ -108,6 +136,7 @@ module.exports = {
extractDisplayName: extractDisplayName,
extractTypeName: extractTypeName,
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 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
var web3Methods = function () {
return [
@ -158,8 +136,8 @@ var setupMethods = function (obj, methods) {
var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({
call: call,
args: args
method: call,
params: args
});
};
});
@ -172,15 +150,15 @@ var setupProperties = function (obj, properties) {
var proto = {};
proto.get = function () {
return web3.provider.send({
call: property.getter
method: property.getter
});
};
if (property.setter) {
proto.set = function (val) {
return web3.provider.send({
call: property.setter,
args: [val]
method: property.setter,
params: [val]
});
};
}
@ -213,29 +191,7 @@ var web3 = {
},
/// used to transform value/string to eth string
/// TODO: use BigNumber.js to parse int
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];
},
toEth: utils.toEth,
/// eth object prototype
eth: {
@ -271,11 +227,6 @@ var web3 = {
return new web3.filter(filter, shhWatch);
}
},
/// @returns true if provider is installed
haveProvider: function() {
return !!web3.provider.provider;
}
};
/// setups all api methods
@ -298,7 +249,6 @@ var shhWatch = {
setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) {
//provider.onmessage = messageHandler; // there will be no async calls, to remove
web3.provider.set(provider);
};

2
libjsqrc/ethereumjs/package.json

@ -1,7 +1,7 @@
{
"name": "ethereum.js",
"namespace": "ethereum",
"version": "0.0.11",
"version": "0.0.13",
"description": "Ethereum Compatible JavaScript API",
"main": "./index.js",
"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 web3 = require('../index.js');
var u = require('./utils.js');
var u = require('./test.utils.js');
describe('web3', function() {
describe('db', function() {

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

@ -1,6 +1,6 @@
var assert = require('assert');
var web3 = require('../index.js');
var u = require('./utils.js');
var u = require('./test.utils.js');
describe('web3', 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 web3 = require('../index.js');
var u = require('./utils.js');
var u = require('./test.utils.js');
describe('web3', 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 web3 = require('../index.js');
var u = require('./utils.js');
var u = require('./test.utils.js');
describe('web3', function() {
u.methodExists(web3, 'sha3');

12
libjsqrc/natspec.js

@ -29,10 +29,20 @@ var getContractMethods = function (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
/// @returns hashmap with all contract's method input variables
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) {
acc[current.name] = params[index];
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)
{
clogS(NetConnect) << "Disabling capability '" << m_host->name() << "'. Reason:" << _problem;
clogS(NetWarn) << "DISABLE: Disabling capability '" << m_host->name() << "'. Reason:" << _problem;
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
{
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run)
return;
@ -409,6 +411,8 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept
void Host::connect(bi::tcp::endpoint const& _ep)
{
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run)
return;
@ -430,6 +434,8 @@ void Host::connect(bi::tcp::endpoint const& _ep)
void Host::connect(std::shared_ptr<Node> const& _n)
{
while (isWorking() && !m_run)
this_thread::sleep_for(chrono::milliseconds(50));
if (!m_run)
return;

17
libp2p/Session.cpp

@ -273,24 +273,24 @@ bool Session::interpret(RLP const& _r)
}
case PingPacket:
{
clogS(NetTriviaSummary) << "Ping";
clogS(NetTriviaSummary) << "Ping";
RLPStream s;
sealAndSend(prep(s, PongPacket));
break;
}
case PongPacket:
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;
case GetPeersPacket:
{
clogS(NetTriviaSummary) << "GetPeers";
clogS(NetTriviaSummary) << "GetPeers";
m_theyRequestedNodes = true;
serviceNodesRequest();
break;
}
case PeersPacket:
clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
m_weRequestedNodes = false;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
@ -369,8 +369,13 @@ bool Session::interpret(RLP const& _r)
{
auto id = _r[0].toInt<unsigned>();
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))
return true;
if (id >= i.second->m_idOffset && id - i.second->m_idOffset < i.second->hostCapability()->messageCount())
{
if (i.second->m_enabled)
return i.second->interpret(id - i.second->m_idOffset, _r);
else
return true;
}
return false;
}
}

13
libqwebthree/QWebThree.cpp

@ -41,20 +41,9 @@ void QWebThree::clientDieing()
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)
{
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
emit processData(formatInput(f), ""); // it's synchronous
emit processData(_json, ""); // it's synchronous
return m_response;
}

92
libserpent/compiler.cpp

@ -77,43 +77,12 @@ Node popwrap(Node node) {
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
programData opcodeify(Node node,
programAux aux=Aux(),
programVerticalAux vaux=verticalAux()) {
std::string symb = "_"+mkUniqueToken();
Metadata m = node.metadata;
// Get variables
if (!aux.vars.size()) {
aux.vars = getVariables(node);
aux.nextVarMem = aux.vars.size() * 32 + 32;
}
// Numbers
if (node.type == TOKEN) {
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") {
std::string varname = node.args[0].val;
// 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);
//std::cerr << varname << " " << printSimple(varNode) << "\n";
// Set variable
@ -173,8 +146,7 @@ programData opcodeify(Node node,
}
// Comments do nothing
else if (node.val == "comment") {
Node* nodelist = nullptr;
return pd(aux, multiToken(nodelist, 0, m), 0);
return pd(aux, astnode("_", m), 0);
}
// Custom operation sequence
// 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
programAux buildDict(Node program, programAux aux, int labelLength) {
void buildDict(Node program, programAux &aux, int labelLength) {
Metadata m = program.metadata;
// Token
if (program.type == TOKEN) {
@ -388,30 +360,24 @@ programAux buildDict(Node program, programAux aux, int labelLength) {
}
// A sub-program (ie. LLL)
else if (program.val == "____CODE") {
programAux auks = Aux();
int step = aux.step;
aux.step = 0;
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();
it != auks.vars.end();
it++) {
aux.vars[(*it).first] = (*it).second;
}
aux.step += auks.step;
aux.step += step;
}
// Normal sub-block
else {
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
Node substDict(Node program, programAux aux, int labelLength) {
void substDict(Node program, programAux aux, int labelLength, std::vector<Node> &out) {
Metadata m = program.metadata;
std::vector<Node> out;
std::vector<Node> inner;
if (program.type == TOKEN) {
if (program.val[0] == '$') {
@ -428,46 +394,32 @@ Node substDict(Node program, programAux aux, int labelLength) {
dist = decimalSub(end, start);
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 (isNumberLike(program)) {
inner = toByteArr(program.val, m);
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 {
for (unsigned i = 0; i < program.args.size(); i++) {
Node n = substDict(program.args[i], aux, labelLength);
if (n.type == TOKEN || n.args.size()) out.push_back(n);
substDict(program.args[i], aux, labelLength, out);
}
}
return astnode("_", out, m);
}
// Compiled fragtree -> compiled fragtree without labels
Node dereference(Node program) {
std::vector<Node> dereference(Node program) {
int sz = treeSize(program) * 4;
int labelLength = 1;
while (sz >= 256) { labelLength += 1; sz /= 256; }
programAux aux = buildDict(program, Aux(), labelLength);
return substDict(program, aux, labelLength);
}
// Dereferenced fragtree -> opcodes
std::vector<Node> flatten(Node derefed) {
programAux aux = Aux();
buildDict(program, aux, labelLength);
std::vector<Node> o;
if (derefed.type == TOKEN) {
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]);
}
}
substDict(program, aux, labelLength, o);
return o;
}
@ -512,12 +464,12 @@ std::vector<Node> deserialize(std::string ser) {
// Fragtree -> bin
std::string assemble(Node fragTree) {
return serialize(flatten(dereference(fragTree)));
return serialize(dereference(fragTree));
}
// Fragtree -> tokens
std::vector<Node> prettyAssemble(Node fragTree) {
return flatten(dereference(fragTree));
return dereference(fragTree);
}
// LLL -> bin

5
libserpent/compiler.h

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

7
libserpent/util.cpp

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

45
libsolidity/AST.cpp

@ -133,7 +133,7 @@ void ContractDefinition::checkIllegalOverrides() const
FunctionDefinition const*& override = functions[name];
if (!override)
override = function.get();
else if (override->isPublic() != function->isPublic() ||
else if (override->getVisibility() != function->getVisibility() ||
override->isDeclaredConst() != function->isDeclaredConst() ||
FunctionType(*override) != FunctionType(*function))
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
@ -475,6 +475,8 @@ void FunctionCall::checkTypeRequirements()
// number of non-mapping members
if (m_arguments.size() != 1)
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()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
m_type = type.getActualType();
@ -487,9 +489,44 @@ void FunctionCall::checkTypeRequirements()
TypePointers const& parameterTypes = functionType->getParameterTypes();
if (parameterTypes.size() != m_arguments.size())
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]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
if (m_names.empty())
{
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,
// but we change it to the type of the first return value until we have structs
if (functionType->getReturnParameterTypes().empty())

41
libsolidity/AST.h

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

72
libsolidity/ExpressionCompiler.cpp

@ -22,6 +22,7 @@
#include <utility>
#include <numeric>
#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/Common.h>
#include <libdevcrypto/SHA3.h>
#include <libsolidity/AST.h>
@ -194,6 +195,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
{
//@todo struct construction
solAssert(_functionCall.getArguments().size() == 1, "");
solAssert(_functionCall.getNames().empty(), "");
Expression const& firstArgument = *_functionCall.getArguments().front();
firstArgument.accept(*this);
appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
@ -201,8 +203,26 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else
{
FunctionType const& function = dynamic_cast<FunctionType const&>(*_functionCall.getExpression().getType());
vector<ASTPointer<Expression const>> arguments = _functionCall.getArguments();
solAssert(arguments.size() == function.getParameterTypes().size(), "");
TypePointers const& parameterTypes = function.getParameterTypes();
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())
{
@ -823,26 +843,58 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ
return length;
}
unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType,
Expression const& _expression, unsigned _memoryOffset)
unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type,
Location const& _location, unsigned _memoryOffset)
{
_expression.accept(*this);
appendTypeConversion(*_expression.getType(), _expectedType, true);
appendTypeConversion(_type, _expectedType, true);
unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize());
if (c_numBytes == 0 || c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_expression.getLocation())
<< errinfo_sourceLocation(_location)
<< errinfo_comment("Type " + _expectedType.toString() + " not yet supported."));
bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING;
bool const c_padToWords = true;
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)
{
m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType());
solAssert(m_currentLValue.isInStorage(), "");
m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true);
FunctionType thisType(_varDecl);
solAssert(thisType.getReturnParameterTypes().size() == 1, "");
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,

4
libsolidity/ExpressionCompiler.h

@ -97,6 +97,10 @@ private:
unsigned appendArgumentCopyToMemory(TypePointers const& _types,
std::vector<ASTPointer<Expression const>> const& _arguments,
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).
/// @returns the number of bytes copied to memory
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);
expectToken(Token::LBRACE);
bool visibilityIsPublic = true;
while (true)
{
Token::Value currentToken = m_scanner->getCurrentToken();
if (currentToken == Token::RBRACE)
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)
functions.push_back(parseFunctionDefinition(visibilityIsPublic, name.get()));
functions.push_back(parseFunctionDefinition(name.get()));
else if (currentToken == Token::STRUCT)
structs.push_back(parseStructDefinition());
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
Token::isElementaryTypeName(currentToken))
{
VarDeclParserOptions options;
options.isPublic = visibilityIsPublic;
options.isStateVariable = true;
stateVariables.push_back(parseVariableDeclaration(options));
expectToken(Token::SEMICOLON);
@ -177,7 +169,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
if (m_scanner->getCurrentToken() == Token::LPAREN)
{
m_scanner->next();
arguments = parseFunctionCallArguments();
arguments = parseFunctionCallListArguments();
nodeFactory.markEndPosition();
expectToken(Token::RPAREN);
}
@ -186,7 +178,22 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
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);
ASTPointer<ASTString> docstring;
@ -201,16 +208,24 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
name = expectIdentifierToken();
ASTPointer<ParameterList> parameters(parseParameterList());
bool isDeclaredConst = false;
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
vector<ASTPointer<ModifierInvocation>> modifiers;
while (true)
{
if (m_scanner->getCurrentToken() == Token::CONST)
Token::Value token = m_scanner->getCurrentToken();
if (token == Token::CONST)
{
isDeclaredConst = true;
m_scanner->next();
}
else if (m_scanner->getCurrentToken() == Token::IDENTIFIER)
else if (token == Token::IDENTIFIER)
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
break;
}
@ -226,7 +241,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
ASTPointer<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block);
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,
returnParameters, block);
}
@ -253,14 +268,18 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOp
ASTNodeFactory nodeFactory(*this);
ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
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;
m_scanner->next();
}
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
if (_options.isStateVariable && Token::isVisibilitySpecifier(token))
visibility = parseVisibilitySpecifier(token);
nodeFactory.markEndPosition();
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(),
_options.isPublic, _options.isStateVariable,
visibility, _options.isStateVariable,
isIndexed);
}
@ -313,7 +332,7 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
if (m_scanner->getCurrentToken() == Token::LPAREN)
{
m_scanner->next();
arguments = parseFunctionCallArguments();
arguments = parseFunctionCallListArguments();
nodeFactory.markEndPosition();
expectToken(Token::RPAREN);
}
@ -573,7 +592,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
ASTPointer<Expression> expression = parseUnaryExpression();
int precedence = Token::precedence(m_scanner->getCurrentToken());
for (; precedence >= _minPrecedence; --precedence)
{
while (Token::precedence(m_scanner->getCurrentToken()) == precedence)
{
Token::Value op = m_scanner->getCurrentToken();
@ -582,7 +600,6 @@ ASTPointer<Expression> Parser::parseBinaryExpression(int _minPrecedence)
nodeFactory.setEndPositionFromNode(right);
expression = nodeFactory.createNode<BinaryOperation>(expression, op, right);
}
}
return expression;
}
@ -648,10 +665,12 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression()
case Token::LPAREN:
{
m_scanner->next();
vector<ASTPointer<Expression>> arguments = parseFunctionCallArguments();
vector<ASTPointer<Expression>> arguments;
vector<ASTPointer<ASTString>> names;
std::tie(arguments, names) = parseFunctionCallArguments();
nodeFactory.markEndPosition();
expectToken(Token::RPAREN);
expression = nodeFactory.createNode<FunctionCall>(expression, arguments);
expression = nodeFactory.createNode<FunctionCall>(expression, arguments, names);
}
break;
default:
@ -704,7 +723,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
return expression;
}
vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
{
vector<ASTPointer<Expression>> arguments;
if (m_scanner->getCurrentToken() != Token::RPAREN)
@ -719,6 +738,32 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
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()
{

7
libsolidity/Parser.h

@ -48,7 +48,6 @@ private:
struct VarDeclParserOptions {
VarDeclParserOptions() {}
bool allowVar = false;
bool isPublic = false;
bool isStateVariable = false;
bool allowIndexed = false;
};
@ -58,7 +57,8 @@ private:
ASTPointer<ImportDirective> parseImportDirective();
ASTPointer<ContractDefinition> parseContractDefinition();
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<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
ASTPointer<ModifierDefinition> parseModifierDefinition();
@ -81,7 +81,8 @@ private:
ASTPointer<Expression> parseUnaryExpression();
ASTPointer<Expression> parseLeftHandSideExpression();
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(PUBLIC, "public", 0) \
K(PRIVATE, "private", 0) \
K(PROTECTED, "protected", 0) \
K(RETURN, "return", 0) \
K(RETURNS, "returns", 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 isCountOp(Value op) { return op == INC || op == DEC; }
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
// (.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):
m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl)
{
TypePointers params({});
vector<string> paramNames({});
TypePointers retParams({_varDecl.getType()});
vector<string> retParamNames({ _varDecl.getName()});
// for now, no input parameters LTODO: change for some things like mapping
TypePointers params;
vector<string> paramNames;
TypePointers retParams;
vector<string> retParamNames;
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(paramNames, m_parameterNames);

7
libsolidity/grammar.txt

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

7
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -28,7 +28,7 @@
#include <liblll/Compiler.h>
#include <libethereum/Client.h>
#include <libwebthree/WebThree.h>
#include <libdevcore/CommonJS.h>
#include <libethcore/CommonJS.h>
#include <libwhisper/Message.h>
#include <libwhisper/WhisperHost.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)
{
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)

4
libweb3jsonrpc/WebThreeStubServerBase.h

@ -36,9 +36,9 @@ namespace dev
{
class WebThreeNetworkFace;
class KeyPair;
struct TransactionSkeleton;
namespace eth
{
struct TransactionSkeleton;
class Interface;
}
namespace shh
@ -122,7 +122,7 @@ public:
std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; }
protected:
virtual bool authenticate(dev::TransactionSkeleton const& _t);
virtual bool authenticate(dev::eth::TransactionSkeleton const& _t);
protected:
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 <QQmlContext>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QWindow>
#include "CodeModel.h"
#include "FileIo.h"
#include "ClientModel.h"
#include "CodeEditorExtensionManager.h"
#include "Exceptions.h"
#include "AppContext.h"
#include "QEther.h"
#include "QVariableDefinition.h"
#include "HttpServer.h"
#include "AppContext.h"
using namespace dev;
using namespace dev::eth;
@ -49,6 +50,7 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_codeModel.reset(new CodeModel(this));
m_clientModel.reset(new ClientModel(this));
m_fileIo.reset(new FileIo());
connect(QApplication::clipboard(), &QClipboard::dataChanged, [this] { emit clipboardChanged();});
}
AppContext::~AppContext()
@ -82,7 +84,7 @@ void AppContext::load()
qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager");
qmlRegisterType<HttpServer>("HttpServer", 1, 0, "HttpServer");
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"));
appLoaded();
}
@ -105,6 +107,12 @@ void AppContext::displayMessageDialog(QString _title, QString _message)
QMetaObject::invokeMethod(dialogWin, "open");
}
QString AppContext::clipboard() const
{
QClipboard *clipboard = QApplication::clipboard();
return clipboard->text();
}
void AppContext::toClipboard(QString _text)
{
QClipboard *clipboard = QApplication::clipboard();

4
mix/AppContext.h

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

41
mix/ClientModel.cpp

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

5
mix/ClientModel.h

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

2
mix/ContractCallDataEncoder.cpp

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

2
mix/DebuggingStateWrapper.cpp

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

222
mix/MixClient.cpp

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

30
mix/MixClient.h

@ -24,8 +24,10 @@
#pragma once
#include <vector>
#include <string>
#include <libethereum/Interface.h>
#include <libethereum/Client.h>
#include <libethereum/CanonBlockChain.h>
#include "MachineStates.h"
namespace dev
@ -33,26 +35,18 @@ namespace dev
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
{
public:
MixClient();
MixClient(std::string const& _dbPath);
virtual ~MixClient();
/// Reset state to the empty state with given balance.
void resetState(u256 _balance);
KeyPair const& userAccount() const { return m_userAccount; }
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
void transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override;
@ -94,18 +88,22 @@ public:
private:
void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state);
void validateBlock(int _block) const;
void noteChanged(h256Set const& _filters);
dev::eth::State const& asOf(int _block) const;
dev::eth::State asOf(int _block) const;
KeyPair m_userAccount;
eth::State m_state;
eth::State m_startState;
OverlayDB m_stateDB;
eth::CanonBlockChain m_bc;
mutable boost::shared_mutex x_state;
mutable std::mutex m_filterLock;
std::map<h256, dev::eth::InstalledFilter> m_filters;
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.hpp>
#include <libdevcore/CommonJS.h>
#include <libethcore/CommonJS.h>
#include "QBigInt.h"
using namespace dev;

2
mix/QBigInt.h

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

2
mix/QVariableDefinition.cpp

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

3
mix/qml/MainContent.qml

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

15
mix/qml/WebCodeEditor.qml

@ -4,6 +4,7 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0
import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
Item {
signal editorTextChanged
@ -29,6 +30,18 @@ Item {
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
id: codeEditorView
anchors.fill: parent
@ -36,6 +49,7 @@ Item {
id: editorBrowser
url: "qrc:///qml/html/codeeditor.html"
anchors.fill: parent
experimental.settings.javascriptCanAccessClipboard: true
onJavaScriptConsoleMessage: {
console.log("editor: " + sourceID + ":" + lineNumber + ":" + message);
}
@ -47,6 +61,7 @@ Item {
setText(currentText, currentMode);
runJavaScript("getTextChanged()", function(result) { });
pollTimer.running = true;
syncClipboard();
}
}

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

@ -29,7 +29,7 @@
var ie = ie_upto10 || ie_11up;
var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
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 presto = /Opera\//.test(navigator.userAgent);
var safari = /Apple Computer/.test(navigator.vendor);

20
mix/qml/html/codeeditor.js

@ -6,6 +6,7 @@ var editor = CodeMirror(document.body, {
autofocus: true,
});
editor.setOption("theme", "solarized dark");
editor.setOption("indentUnit", 4);
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() {
return editor.changeRegistered;
};
getText = function() {
editor.changeRegistered = false;
return editor.getValue();
@ -42,3 +56,7 @@ setText = function(text) {
setMode = function(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.Layouts 1.1
import QtQuick.Window 2.1
import QtQuick.PrivateWidgets 1.1
import Qt.labs.settings 1.0
import org.ethereum.qml.QEther 1.0

5
pullSerpent.sh

@ -2,10 +2,11 @@
opwd="$PWD"
cd ../serpent
git stash
git pull
git stash pop
cp bignum.* compiler.* funcs.* lllparser.* opcodes.h parser.* rewriter.* tokenize.* util.* ../cpp-ethereum/libserpent/
cp cmdline.* "$opwd/sc/"
cp pyserpent.* "$opwd/libpyserpent/"
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";
}
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") {
std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n";
@ -88,9 +88,6 @@ int main(int argv, char** argc) {
else if (command == "serialize") {
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") {
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_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)
{
char const* sourceCode = "contract test {\n"
@ -885,7 +905,7 @@ BOOST_AUTO_TEST_CASE(constructor)
BOOST_AUTO_TEST_CASE(simple_accessor)
{
char const* sourceCode = "contract test {\n"
" uint256 data;\n"
" uint256 public data;\n"
" function test() {\n"
" data = 8;\n"
" }\n"
@ -897,10 +917,10 @@ BOOST_AUTO_TEST_CASE(simple_accessor)
BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
{
char const* sourceCode = "contract test {\n"
" uint256 data;\n"
" string6 name;\n"
" hash a_hash;\n"
" address an_address;\n"
" uint256 public data;\n"
" string6 public name;\n"
" hash public a_hash;\n"
" address public an_address;\n"
" function test() {\n"
" data = 8;\n"
" name = \"Celina\";\n"
@ -908,7 +928,6 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
" an_address = address(0x1337);\n"
" super_secret_data = 42;\n"
" }\n"
" private:"
" uint256 super_secret_data;"
"}\n";
compileAndRun(sourceCode);
@ -919,6 +938,27 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
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)
{
char const* sourceCode = "contract test {\n"
@ -1490,8 +1530,7 @@ BOOST_AUTO_TEST_CASE(functions_called_by_constructor)
setName("abc");
}
function getName() returns (string3 ret) { return name; }
private:
function setName(string3 _name) { name = _name; }
function setName(string3 _name) private { name = _name; }
})";
compileAndRun(sourceCode);
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_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)
{
char const* text = R"(
@ -636,7 +654,9 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
" function fun() {\n"
" uint64(2);\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";
ASTPointer<SourceUnit> source;
@ -644,10 +664,27 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
BOOST_REQUIRE(function->hasDeclaration());
BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
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)
@ -668,16 +705,19 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
" function fun() {\n"
" uint64(2);\n"
" }\n"
"private:\n"
"uint256 foo;\n"
"uint256 private foo;\n"
"uint256 protected bar;\n"
"}\n";
ASTPointer<SourceUnit> source;
ContractDefinition const* contract;
BOOST_CHECK_NO_THROW(source = parseTextAndResolveNamesWithChecks(text));
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");
function = retrieveFunctionBySignature(contract, "bar()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a protected variable should not exist");
}
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_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()
}

49
test/SolidityParser.cpp

@ -124,14 +124,30 @@ BOOST_AUTO_TEST_CASE(single_function_param)
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)
{
ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n"
" private:\n"
" uint256 stateVar;\n"
" public:\n"
" uint256 stateVar;\n"
" /// This is a test function\n"
" function functionName(hash hashin) returns (hash hashout) {}\n"
"}\n";
@ -162,9 +178,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
ASTPointer<ContractDefinition> contract;
ASTPointer<FunctionDefinition> function;
char const* text = "contract test {\n"
" private:\n"
" uint256 stateVar;\n"
" public:\n"
" /// This is test function 1\n"
" function functionName1(hash hashin) returns (hash hashout) {}\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_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()
}

5
test/commonjs.cpp

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

2
test/fork.cpp

@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp>
#include <libethereum/Client.h>
#include <libethereum/BlockChain.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h>
#include "TestHelper.h"
using namespace std;

8
test/genesis.cpp

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

2
test/jsonrpc.cpp

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

2
test/state.cpp

@ -24,7 +24,7 @@
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/BlockChain.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>

4
test/stateOriginal.cpp

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

2
test/txTest.cpp

@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp>
#include <libethereum/Client.h>
#include <libethereum/BlockChain.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/EthereumHost.h>
#include "TestHelper.h"
using namespace std;

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

Loading…
Cancel
Save