Browse Source

Merge remote-tracking branch 'up/develop' into bugFix2

Conflicts:
	test/webthreestubclient.h
cl-refactor
yann300 10 years ago
parent
commit
13fa394f60
  1. 1
      CMakeLists.txt
  2. 2
      alethzero/Context.h
  3. 129
      alethzero/MainWin.cpp
  4. 2
      alethzero/MainWin.h
  5. 33
      alethzero/Transact.cpp
  6. 2
      alethzero/Transact.ui
  7. 13
      cmake/EthCompilerSettings.cmake
  8. 43
      docker/Dockerfile
  9. 31
      docker/README.md
  10. 23
      docker/supervisord.conf
  11. 51
      eth/main.cpp
  12. 41
      ethminer/CMakeLists.txt
  13. 39
      ethminer/Farm.h
  14. 28
      ethminer/PhoneHome.h
  15. 4
      ethminer/farm.json
  16. 483
      ethminer/main.cpp
  17. 3
      ethminer/phonehome.json
  18. 2
      evmjit/libevmjit-cpp/CMakeLists.txt
  19. 21
      libdevcore/Base64.h
  20. 6
      libdevcore/CMakeLists.txt
  21. 28
      libdevcore/CommonData.h
  22. 1
      libdevcore/Exceptions.h
  23. 2
      libdevcore/Log.h
  24. 6
      libdevcrypto/CMakeLists.txt
  25. 4
      libdevcrypto/Common.cpp
  26. 4
      libethash/CMakeLists.txt
  27. 0
      libethcore/ABI.cpp
  28. 8
      libethcore/ABI.h
  29. 6
      libethcore/CMakeLists.txt
  30. 5
      libethcore/Common.cpp
  31. 2
      libethcore/Common.h
  32. 4
      libethcore/Ethash.cpp
  33. 4
      libethcore/EthashAux.cpp
  34. 2
      libethcore/EthashAux.h
  35. 158
      libethcore/ICAP.cpp
  36. 107
      libethcore/ICAP.h
  37. 19
      libethereum/BlockChain.cpp
  38. 2
      libethereum/BlockChain.h
  39. 6
      libethereum/CMakeLists.txt
  40. 60
      libethereum/Client.cpp
  41. 9
      libethereum/Client.h
  42. 4
      libethereum/ClientBase.cpp
  43. 3
      libethereum/ClientBase.h
  44. 6
      libethereum/Interface.h
  45. 2
      libethereum/Transaction.cpp
  46. 8
      libethereum/Transaction.h
  47. 6
      libethereumx/CMakeLists.txt
  48. 6
      libevm/CMakeLists.txt
  49. 13
      libevmcore/AssemblyItem.h
  50. 6
      libevmcore/CMakeLists.txt
  51. 176
      libevmcore/CommonSubexpressionEliminator.cpp
  52. 20
      libevmcore/CommonSubexpressionEliminator.h
  53. 24
      libevmcore/ExpressionClasses.cpp
  54. 10
      libevmcore/ExpressionClasses.h
  55. 1
      libjsqrc/ethereumjs/.travis.yml
  56. 34
      libjsqrc/ethereumjs/README.md
  57. 2
      libjsqrc/ethereumjs/bower.json
  58. 1644
      libjsqrc/ethereumjs/dist/web3-light.js
  59. 46
      libjsqrc/ethereumjs/dist/web3-light.js.map
  60. 3
      libjsqrc/ethereumjs/dist/web3-light.min.js
  61. 6998
      libjsqrc/ethereumjs/dist/web3.js
  62. 50
      libjsqrc/ethereumjs/dist/web3.js.map
  63. 4
      libjsqrc/ethereumjs/dist/web3.min.js
  64. 57
      libjsqrc/ethereumjs/example/contract.html
  65. 77
      libjsqrc/ethereumjs/example/contract_with_array.html
  66. 119
      libjsqrc/ethereumjs/example/event.html
  67. 65
      libjsqrc/ethereumjs/example/event_inc.html
  68. 143
      libjsqrc/ethereumjs/lib/solidity/abi.js
  69. 329
      libjsqrc/ethereumjs/lib/solidity/coder.js
  70. 114
      libjsqrc/ethereumjs/lib/solidity/formatters.js
  71. 105
      libjsqrc/ethereumjs/lib/solidity/param.js
  72. 77
      libjsqrc/ethereumjs/lib/solidity/types.js
  73. 30
      libjsqrc/ethereumjs/lib/solidity/utils.js
  74. 3
      libjsqrc/ethereumjs/lib/utils/config.js
  75. 42
      libjsqrc/ethereumjs/lib/utils/utils.js
  76. 2
      libjsqrc/ethereumjs/lib/version.json
  77. 17
      libjsqrc/ethereumjs/lib/web3.js
  78. 184
      libjsqrc/ethereumjs/lib/web3/contract.js
  79. 22
      libjsqrc/ethereumjs/lib/web3/errors.js
  80. 13
      libjsqrc/ethereumjs/lib/web3/eth.js
  81. 246
      libjsqrc/ethereumjs/lib/web3/event.js
  82. 57
      libjsqrc/ethereumjs/lib/web3/filter.js
  83. 15
      libjsqrc/ethereumjs/lib/web3/formatters.js
  84. 151
      libjsqrc/ethereumjs/lib/web3/function.js
  85. 18
      libjsqrc/ethereumjs/lib/web3/httpprovider.js
  86. 2
      libjsqrc/ethereumjs/lib/web3/method.js
  87. 6
      libjsqrc/ethereumjs/lib/web3/requestmanager.js
  88. 2
      libjsqrc/ethereumjs/lib/web3/shh.js
  89. 42
      libjsqrc/ethereumjs/lib/web3/signature.js
  90. 2
      libjsqrc/ethereumjs/package-init.js
  91. 7
      libjsqrc/ethereumjs/package.js
  92. 4
      libjsqrc/ethereumjs/package.json
  93. 14
      libjsqrc/ethereumjs/test/abi.inputParser.js
  94. 96
      libjsqrc/ethereumjs/test/abi.outputParser.js
  95. 68
      libjsqrc/ethereumjs/test/coder.decodeParam.js
  96. 91
      libjsqrc/ethereumjs/test/coder.encodeParam.js
  97. 147
      libjsqrc/ethereumjs/test/contract.js
  98. 180
      libjsqrc/ethereumjs/test/event.decode.js
  99. 206
      libjsqrc/ethereumjs/test/event.encode.js
  100. 113
      libjsqrc/ethereumjs/test/event.inputParser.js

1
CMakeLists.txt

@ -354,6 +354,7 @@ if (TOOLS)
add_subdirectory(rlp)
add_subdirectory(abi)
add_subdirectory(ethminer)
add_subdirectory(eth)
if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug")

2
alethzero/Context.h

@ -62,7 +62,7 @@ public:
virtual QString pretty(dev::Address _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0;
virtual QString render(dev::Address _a) const = 0;
virtual dev::Address fromString(QString const& _a) const = 0;
virtual std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
};

129
alethzero/MainWin.cpp

@ -46,6 +46,7 @@
#include <libdevcrypto/FileSystem.h>
#include <libethcore/CommonJS.h>
#include <libethcore/EthashAux.h>
#include <libethcore/ICAP.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h>
@ -217,6 +218,7 @@ Main::Main(QWidget *parent) :
Main::~Main()
{
m_httpConnector->StopListening();
writeSettings();
// Must do this here since otherwise m_ethereum'll be deleted (and therefore clearWatches() called by the destructor)
// *after* the client is dead.
@ -326,7 +328,8 @@ void Main::installWatches()
Address Main::getNameReg() const
{
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)).output);
return Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
// return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)1)).output);
}
Address Main::getCurrencies() const
@ -512,137 +515,65 @@ QString Main::pretty(dev::Address _a) const
if (g_newNameReg)
{
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("nameOf(address)", _a)).output)));
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("getName(address)", _a)).output)));
if (s.size())
return s;
}
h256 n;
return fromRaw(n);
}
template <size_t N> inline string toBase36(FixedHash<N> const& _h)
{
static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typename FixedHash<N>::Arith a = _h;
std::string ret;
for (; a > 0; a /= 36)
ret = c_alphabet[(unsigned)a % 36] + ret;
return ret;
}
template <size_t N> inline FixedHash<N> fromBase36(string const& _h)
{
typename FixedHash<N>::Arith ret = 0;
for (char c: _h)
ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10));
return ret;
}
static string iban(std::string _c, std::string _d)
{
boost::to_upper(_c);
boost::to_upper(_d);
auto totStr = _d + _c + "00";
bigint tot = 0;
for (char x: totStr)
if (x >= 'A')
tot = tot * 100 + x - 'A' + 10;
else
tot = tot * 10 + x - '0';
unsigned check = (unsigned)(u256)(98 - tot % 97);
ostringstream out;
out << _c << setfill('0') << setw(2) << check << _d;
return out.str();
}
static std::pair<string, string> fromIban(std::string _iban)
{
if (_iban.size() < 4)
return std::make_pair(string(), string());
boost::to_upper(_iban);
std::string c = _iban.substr(0, 2);
std::string d = _iban.substr(4);
if (iban(c, d) != _iban)
return std::make_pair(string(), string());
return make_pair(c, d);
}
static string directICAP(dev::Address _a)
{
if (!!_a[0])
return string();
std::string d = toBase36<Address::size>(_a);
while (d.size() < 30)
d = "0" + d;
return iban("XE", d);
}
static Address fromICAP(std::string const& _s)
{
std::string country;
std::string data;
std::tie(country, data) = fromIban(_s);
if (country.empty())
return Address();
if (country == "XE" && data.size() == 30)
// Direct ICAP
return fromBase36<Address::size>(data);
// TODO: Indirect ICAP
return Address();
return QString();
}
QString Main::render(dev::Address _a) const
{
QString p = pretty(_a);
if (!_a[0])
p += QString(p.isEmpty() ? "" : " ") + QString::fromStdString(directICAP(_a));
if (!p.isEmpty())
return p + " (" + QString::fromStdString(_a.abridged()) + ")";
return QString::fromStdString(_a.abridged());
}
string32 fromString(string const& _s)
{
string32 ret;
for (unsigned i = 0; i < 32 && i <= _s.size(); ++i)
ret[i] = i < _s.size() ? _s[i] : 0;
return ret;
QString n;
try {
n = QString::fromStdString(ICAP(_a).encoded());
}
catch (...) {
n = QString::fromStdString(_a.abridged());
}
return p.isEmpty() ? n : (p + " " + n);
}
Address Main::fromString(QString const& _n) const
pair<Address, bytes> Main::fromString(QString const& _n) const
{
if (_n == "(Create Contract)")
return Address();
return make_pair(Address(), bytes());
auto g_newNameReg = getNameReg();
if (g_newNameReg)
{
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addressOf(string32)", ::fromString(_n.toStdString()))).output);
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n.toStdString()))).output);
if (a)
return a;
return make_pair(a, bytes());
}
if (_n.size() == 40)
{
try
{
return Address(fromHex(_n.toStdString(), WhenError::Throw));
return make_pair(Address(fromHex(_n.toStdString(), WhenError::Throw)), bytes());
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, address rejected";
cwarn << boost::diagnostic_information(_e);
return Address();
return make_pair(Address(), bytes());
}
catch (...)
{
cwarn << "address rejected";
return Address();
return make_pair(Address(), bytes());
}
}
else if (Address a = fromICAP(_n.toStdString()))
return a;
else
return Address();
try {
return ICAP::decoded(_n.toStdString()).address([&](Address const& a, bytes const& b) -> bytes
{
return ethereum()->call(a, b).output;
}, g_newNameReg);
}
catch (...) {}
return make_pair(Address(), bytes());
}
QString Main::lookup(QString const& _a) const
@ -1440,7 +1371,7 @@ void Main::on_inject_triggered()
try
{
bytes b = fromHex(s.toStdString(), WhenError::Throw);
ethereum()->inject(&b);
ethereum()->injectTransaction(b);
}
catch (BadHexCharacter& _e)
{

2
alethzero/MainWin.h

@ -83,7 +83,7 @@ public:
QString pretty(dev::Address _a) const override;
QString prettyU256(dev::u256 _n) const override;
QString render(dev::Address _a) const override;
dev::Address fromString(QString const& _a) const override;
std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override;
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }

33
alethzero/Transact.cpp

@ -30,10 +30,12 @@
#include <QMessageBox>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#if ETH_SOLIDITY || !ETH_TRUE
#include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/AST.h>
#include <libsolidity/SourceReferenceFormatter.h>
#endif
#include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
@ -113,7 +115,7 @@ void Transact::updateDestination()
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)))
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)).first)
ui->destination->removeItem(i--);
}
@ -139,10 +141,25 @@ void Transact::updateFee()
void Transact::on_destination_currentTextChanged(QString)
{
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
if (Address a = m_context->fromString(ui->destination->currentText()))
ui->calculatedName->setText(m_context->render(a));
{
auto p = m_context->fromString(ui->destination->currentText());
if (p.first)
ui->calculatedName->setText(m_context->render(p.first));
else
ui->calculatedName->setText("Unknown Address");
if (!p.second.empty())
{
m_data = p.second;
ui->data->setPlainText(QString::fromStdString("0x" + toHex(m_data)));
ui->data->setEnabled(false);
}
else if (!ui->data->isEnabled())
{
m_data.clear();
ui->data->setPlainText("");
ui->data->setEnabled(true);
}
}
else
ui->calculatedName->setText("Create Contract");
rejigData();
@ -199,7 +216,7 @@ static tuple<vector<string>, bytes, string> userInputToCode(string const& _user,
boost::replace_all_copy(u, " ", "");
data = fromHex(u);
}
#if ETH_SOLIDITY
#if ETH_SOLIDITY || !ETH_TRUE
else if (sourceIsSolidity(_user))
{
dev::solidity::CompilerStack compiler(true);
@ -329,7 +346,8 @@ void Transact::rejigData()
er = ethereum()->create(s, value(), m_data, gasNeeded, gasPrice());
else
{
to = m_context->fromString(ui->destination->currentText());
// TODO: cache like m_data.
to = m_context->fromString(ui->destination->currentText()).first;
er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
}
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
@ -415,7 +433,8 @@ void Transact::on_send_clicked()
#endif
}
else
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
// TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()).first, m_data, ui->gas->value(), gasPrice());
close();
}
@ -434,7 +453,7 @@ void Transact::on_debug_clicked()
State st(ethereum()->postState());
Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s);
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s);
Debugger dw(m_context, this);
Executive e(st, ethereum()->blockChain(), 0);
dw.populate(e, t);

2
alethzero/Transact.ui

@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
<string>Transact</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1" colspan="2">

13
cmake/EthCompilerSettings.cmake

@ -8,7 +8,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")
set(ETH_SHARED 1)
if (PROFILING)
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
@ -31,7 +30,6 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG")
set(ETH_SHARED 1)
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX")
@ -55,8 +53,10 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# stack size 16MB
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216")
# windows likes static
set(ETH_STATIC 1)
if (NOT ETH_STATIC)
message("Forcing static linkage for MSVC.")
set(ETH_STATIC 1)
endif ()
else ()
message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif ()
@ -72,3 +72,8 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
endif ()
endif ()
if(ETH_STATIC)
set(BUILD_SHARED_LIBS OFF)
else()
set(BUILD_SHARED_LIBS ON)
endif(ETH_STATIC)

43
docker/Dockerfile

@ -1,36 +1,31 @@
FROM ubuntu:14.04
FROM ubuntu:utopic
MAINTAINER caktux
ENV DEBIAN_FRONTEND noninteractive
# Usual update / upgrade
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get upgrade -q -y
RUN apt-get dist-upgrade -q -y
# Ethereum dependencies
RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget
RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev
RUN apt-get install -qy libncurses5-dev libcurl4-openssl-dev wget
RUN apt-get install -qy libjsoncpp-dev libargtable2-dev libmicrohttpd-dev
# Let our containers upgrade themselves
RUN apt-get install -q -y unattended-upgrades
# Ethereum PPA
RUN apt-get install -qy software-properties-common
# Install Ethereum
RUN apt-get install -q -y software-properties-common
RUN add-apt-repository ppa:ethereum/ethereum
RUN add-apt-repository ppa:ethereum/ethereum-dev
RUN apt-get update
RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev
RUN apt-get install -q -y eth
# LLVM-3.5
RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main\ndeb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main" > /etc/apt/sources.list.d/llvm-trusty.list
RUN apt-get update
RUN apt-get install -qy llvm-3.5 libedit-dev
# Install supervisor
RUN apt-get install -q -y supervisor
# Fix llvm-3.5 cmake paths
RUN mkdir -p /usr/lib/llvm-3.5/share/llvm && ln -s /usr/share/llvm-3.5/cmake /usr/lib/llvm-3.5/share/llvm/cmake
# Add supervisor configs
ADD supervisord.conf supervisord.conf
# Build Ethereum (HEADLESS)
RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum
RUN mkdir -p cpp-ethereum/build
RUN cd cpp-ethereum/build && cmake .. -DHEADLESS=1 -DLLVM_DIR=/usr/share/llvm-3.5/cmake -DEVMJIT=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install
RUN ldconfig
EXPOSE 8080
EXPOSE 30303
ENTRYPOINT ["/usr/local/bin/eth"]
CMD ["-n", "-c", "/supervisord.conf"]
ENTRYPOINT ["/usr/bin/supervisord"]

31
docker/README.md

@ -1,17 +1,30 @@
# Dockerfile for cpp-ethereum
Dockerfile to build a bleeding edge cpp-ethereum docker image from source
docker build -t cppeth < Dockerfile
### Quick usage
Run a simple peer server
docker run -d ethereum/client-cpp
docker run -i cppeth -m off -o peer -x 256
### Building
GUI is compiled but not exposed. You can mount /cpp-ethereum/build to access binaries:
Dockerfile to build a cpp-ethereum docker image from source
cid = $(docker run -i -v /cpp-ethereum/build cppeth -m off -o peer -x 256)
docker inspect $cid # <-- Find volume path in JSON output
docker build -t cpp-ethereum .
You may also modify the Docker image to run the GUI and expose a
ssh/VNC server in order to tunnel an X11 or VNC session.
### Running
docker run -d cpp-ethereum
### Usage
First enter the container:
docker exec -it <container name> bash
Inspect logs:
cat /var/log/cpp-ethereum.log
cat /var/log/cpp-ethereum.err
Restart supervisor service:
supervisorctl restart cpp-ethereum

23
docker/supervisord.conf

@ -0,0 +1,23 @@
[supervisord]
nodaemon=false
[program:eth]
priority=30
directory=/
command=eth --bootstrap --json-rpc
user=root
autostart=true
autorestart=true
startsecs=10
stopsignal=QUIT
stdout_logfile=/var/log/eth.log
stderr_logfile=/var/log/eth.err
[unix_http_server]
file=%(here)s/supervisor.sock
[supervisorctl]
serverurl=unix://%(here)s/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

51
eth/main.cpp

@ -1010,26 +1010,13 @@ int main(int argc, char** argv)
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
try
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
switch (web3.ethereum()->injectBlock(block))
{
futureTime++;
}
catch (...)
{
bad++;
case ImportResult::Success: good++; break;
case ImportResult::AlreadyKnown: alreadyHave++; break;
case ImportResult::UnknownParent: unknownParent++; break;
case ImportResult::FutureTime: futureTime++; break;
default: bad++; break;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
@ -1137,13 +1124,33 @@ int main(int argc, char** argv)
else if (c && cmd == "setblockfees")
{
iss >> blockFees;
gasPricer->setRefBlockFees(u256(blockFees * 1000));
try
{
gasPricer->setRefBlockFees(u256(blockFees * 1000));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
cout << "Block fees: " << blockFees << endl;
}
else if (c && cmd == "setetherprice")
{
iss >> etherPrice;
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice));
if (etherPrice == 0)
cout << "ether price cannot be set to zero" << endl;
else
{
try
{
gasPricer->setRefPrice(u256(double(ether / 1000) / etherPrice));
}
catch (Overflow const& _e)
{
cout << boost::diagnostic_information(_e);
}
}
cout << "ether Price: " << etherPrice << endl;
}
else if (c && cmd == "setpriority")
@ -1317,9 +1324,9 @@ int main(int argc, char** argv)
{
string hexAddr;
u256 amount;
int size = hexAddr.length();
iss >> hexAddr >> amount;
int size = hexAddr.length();
if (size < 40)
{
if (size > 0)

41
ethminer/CMakeLists.txt

@ -0,0 +1,41 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
set(EXECUTABLE ethminer)
file(GLOB HEADERS "*.h")
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_dependencies(${EXECUTABLE} BuildInfo.h)
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
if (READLINE_FOUND)
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
endif()
if (JSONRPC)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES})
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls(${EXECUTABLE} CURL_DLLS)
endif()
endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethash)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin )

39
ethminer/Farm.h

@ -0,0 +1,39 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_FARM_H_
#define JSONRPC_CPP_STUB_FARM_H_
#include <jsonrpccpp/client.h>
class Farm : public jsonrpc::Client
{
public:
Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getWork",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
p.append(param3);
Json::Value result = this->CallMethod("eth_submitWork",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
#endif //JSONRPC_CPP_STUB_FARM_H_

28
ethminer/PhoneHome.h

@ -0,0 +1,28 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_
#define JSONRPC_CPP_STUB_PHONEHOME_H_
#include <jsonrpccpp/client.h>
class PhoneHome : public jsonrpc::Client
{
public:
PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("report_benchmark",p);
if (result.isInt())
return result.asInt();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
#endif //JSONRPC_CPP_STUB_PHONEHOME_H_

4
ethminer/farm.json

@ -0,0 +1,4 @@
[
{ "name": "eth_getWork", "params": [], "order": [], "returns": []},
{ "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true}
]

483
ethminer/main.cpp

@ -0,0 +1,483 @@
/*
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 main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Ethereum client.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#include <libdevcrypto/FileSystem.h>
#include <libevmcore/Instruction.h>
#include <libdevcore/StructuredLogger.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/EthashAux.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libethereum/All.h>
#include <libwebthree/WebThree.h>
#if ETH_JSONRPC || !ETH_TRUE
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#endif
#include "BuildInfo.h"
#if ETH_JSONRPC || !ETH_TRUE
#include "PhoneHome.h"
#include "Farm.h"
#endif
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::eth;
using namespace boost::algorithm;
using dev::eth::Instruction;
#undef RETURN
bool isTrue(std::string const& _m)
{
return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
}
bool isFalse(std::string const& _m)
{
return _m == "off" || _m == "no" || _m == "false" || _m == "0";
}
void help()
{
cout
<< "Usage ethminer [OPTIONS]" << endl
<< "Options:" << endl << endl
#if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl
<< " -F,--farm <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl
#endif
<< "Benchmarking mode:" << endl
<< " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl
<< " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl
#if ETH_JSONRPC || !ETH_TRUE
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl
#endif
<< "DAG creation mode:" << endl
<< " -D,--create-dag <number> Create the DAG in preparation for mining on given block and exit." << endl
<< "General Options:" << endl
<< " -C,--cpu When mining, use the CPU." << endl
<< " -G,--opencl When mining use the GPU via OpenCL." << endl
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl
;
exit(0);
}
string credits()
{
std::ostringstream cout;
cout
<< "Ethereum (++) " << dev::Version << endl
<< " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl
<< " Based on a design by Vitalik Buterin." << endl << endl;
return cout.str();
}
void version()
{
cout << "eth version " << dev::Version << endl;
cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl;
cout << "Client database version: " << dev::eth::c_databaseVersion << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
}
void doInitDAG(unsigned _n)
{
BlockInfo bi;
bi.number = _n;
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl;
Ethash::prep(bi);
exit(0);
}
enum class OperationMode
{
DAGInit,
Benchmark,
Farm
};
enum class MinerType
{
CPU,
GPU
};
void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5)
{
BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18;
cdebug << genesis.boundary();
GenericFarm<Ethash> f;
f.onSolutionFound([&](ProofOfWork::Solution) { return false; });
string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : "";
cout << "Benchmarking on platform: " << platformInfo << endl;
cout << "Preparing DAG..." << endl;
Ethash::prep(genesis);
genesis.difficulty = u256(1) << 63;
genesis.noteDirty();
f.setWork(genesis);
if (_m == MinerType::CPU)
f.startCPU();
else if (_m == MinerType::GPU)
f.startGPU();
map<uint64_t, MiningProgress> results;
uint64_t mean = 0;
uint64_t innerMean = 0;
for (unsigned i = 0; i <= _trials; ++i)
{
if (!i)
cout << "Warming up..." << endl;
else
cout << "Trial " << i << "... " << flush;
this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration));
auto mp = f.miningProgress();
f.resetMiningProgress();
if (!i)
continue;
auto rate = mp.rate();
cout << rate << endl;
results[rate] = mp;
mean += rate;
if (i > 1 && i < 5)
innerMean += rate;
}
f.stop();
cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl;
cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl;
(void)_phoneHome;
#if ETH_JSONRPC || !ETH_TRUE
if (_phoneHome)
{
cout << "Phoning home to find world ranking..." << endl;
jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark");
PhoneHome rpc(client);
try
{
unsigned ranking = rpc.report_benchmark(platformInfo, innerMean);
cout << "Ranked: " << ranking << " of all benchmarks." << endl;
}
catch (...)
{
cout << "Error phoning home. ET is sad." << endl;
}
}
#endif
exit(0);
}
struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; };
struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; };
void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
{
(void)_m;
(void)_remote;
(void)_recheckPeriod;
#if ETH_JSONRPC || !ETH_TRUE
jsonrpc::HttpClient client(_remote);
Farm rpc(client);
GenericFarm<Ethash> f;
if (_m == MinerType::CPU)
f.startCPU();
else if (_m == MinerType::GPU)
f.startGPU();
ProofOfWork::WorkPackage current;
while (true)
try
{
bool completed = false;
ProofOfWork::Solution solution;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
solution = sol;
return completed = true;
});
for (unsigned i = 0; !completed; ++i)
{
if (current)
cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress();
else
cnote << "Getting work package...";
Json::Value v = rpc.eth_getWork();
h256 hh(v[0].asString());
if (hh != current.headerHash)
{
current.headerHash = hh;
current.seedHash = h256(v[1].asString());
current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight);
cnote << "Got work package:" << current.headerHash << " < " << current.boundary;
f.setWork(current);
}
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
}
cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "...";
bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash));
if (ok)
clog(HappyChannel) << "Submitted and accepted.";
else
clog(SadChannel) << "Not accepted.";
current.reset();
}
catch (jsonrpc::JsonRpcException&)
{
for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1)))
cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r";
cerr << endl;
}
#endif
exit(0);
}
int main(int argc, char** argv)
{
// Init defaults
Defaults::get();
/// Operating mode.
OperationMode mode = OperationMode::Farm;
/// Mining options
MinerType minerType = MinerType::CPU;
unsigned openclPlatform = 0;
unsigned openclDevice = 0;
unsigned miningThreads = UINT_MAX;
/// DAG initialisation param.
unsigned initDAG = 0;
/// Benchmarking params
bool phoneHome = true;
unsigned benchmarkWarmup = 3;
unsigned benchmarkTrial = 3;
unsigned benchmarkTrials = 5;
/// Farm params
string farmURL = "http://127.0.0.1:8080";
unsigned farmRecheckPeriod = 500;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
{
mode = OperationMode::Farm;
farmURL = argv[++i];
}
else if (arg == "--farm-recheck" && i + 1 < argc)
try {
farmRecheckPeriod = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--opencl-platform" && i + 1 < argc)
try {
openclPlatform = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--opencl-device" && i + 1 < argc)
try {
openclDevice = stol(argv[++i]);
miningThreads = 1;
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--phone-home" && i + 1 < argc)
{
string m = argv[++i];
if (isTrue(m))
phoneHome = true;
else if (isFalse(m))
phoneHome = false;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--benchmark-warmup" && i + 1 < argc)
try {
benchmarkWarmup = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-trial" && i + 1 < argc)
try {
benchmarkTrial = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-trials" && i + 1 < argc)
try {
benchmarkTrials = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "-C" || arg == "--cpu")
minerType = MinerType::CPU;
else if (arg == "-G" || arg == "--opencl")
minerType = MinerType::GPU;
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{
string m = boost::to_lower_copy(string(argv[++i]));
mode = OperationMode::DAGInit;
try
{
initDAG = stol(m);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
{
string m;
try
{
BlockInfo bi;
m = boost::to_lower_copy(string(argv[++i]));
h256 powHash(m);
m = boost::to_lower_copy(string(argv[++i]));
h256 seedHash;
if (m.size() == 64 || m.size() == 66)
seedHash = h256(m);
else
seedHash = EthashAux::seedHash(stol(m));
m = boost::to_lower_copy(string(argv[++i]));
bi.difficulty = u256(m);
auto boundary = bi.boundary();
m = boost::to_lower_copy(string(argv[++i]));
bi.nonce = h64(m);
auto r = EthashAux::eval(seedHash, powHash, bi.nonce);
bool valid = r.value < boundary;
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl;
cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl;
cout << " with seed as " << seedHash << endl;
if (valid)
cout << "(mixHash = " << r.mixHash << ")" << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl;
exit(0);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "-M" || arg == "--benchmark")
mode = OperationMode::Benchmark;
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc)
{
try {
miningThreads = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
}
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
g_logVerbosity = atoi(argv[++i]);
else if (arg == "-h" || arg == "--help")
help();
else if (arg == "-V" || arg == "--version")
version();
else
{
cerr << "Invalid argument: " << arg << endl;
exit(-1);
}
}
if (minerType == MinerType::CPU)
ProofOfWork::CPUMiner::setNumInstances(miningThreads);
else if (minerType == MinerType::GPU)
{
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
ProofOfWork::GPUMiner::setNumInstances(miningThreads);
}
if (mode == OperationMode::DAGInit)
doInitDAG(initDAG);
if (mode == OperationMode::Benchmark)
doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials);
if (mode == OperationMode::Farm)
doFarm(minerType, farmURL, farmRecheckPeriod);
return 0;
}

3
ethminer/phonehome.json

@ -0,0 +1,3 @@
[
{ "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 }
]

2
evmjit/libevmjit-cpp/CMakeLists.txt

@ -15,7 +15,7 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # add PIC for archive
endif()
add_library(${TARGET_NAME} ${SOURCES})
add_library(${TARGET_NAME} STATIC ${SOURCES})
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs")
include_directories(../..)

21
libdevcore/Base64.h

@ -30,7 +30,8 @@
#include <vector>
#include <string>
#include <libdevcore/Common.h>
#include "Common.h"
#include "FixedHash.h"
namespace dev
{
@ -38,4 +39,22 @@ namespace dev
std::string toBase64(bytesConstRef _in);
bytes fromBase64(std::string const& _in);
template <size_t N> inline std::string toBase36(FixedHash<N> const& _h)
{
static char const* c_alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typename FixedHash<N>::Arith a = _h;
std::string ret;
for (; a > 0; a /= 36)
ret = c_alphabet[(unsigned)a % 36] + ret;
return ret;
}
template <size_t N> inline FixedHash<N> fromBase36(std::string const& _h)
{
typename FixedHash<N>::Arith ret = 0;
for (char c: _h)
ret = ret * 36 + (c < 'A' ? c - '0' : (c - 'A' + 10));
return ret;
}
}

6
libdevcore/CMakeLists.txt

@ -20,11 +20,7 @@ set(EXECUTABLE devcore)
file(GLOB HEADERS "*.h")
if(ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})

28
libdevcore/CommonData.h

@ -41,17 +41,22 @@ enum class WhenError
Throw = 1,
};
enum class HexPrefix
{
DontAdd = 0,
Add = 1,
};
/// Convert a series of bytes to the corresponding string of hex duplets.
/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte.
/// @example toHex("A\x69") == "4169"
template <class _T>
std::string toHex(_T const& _data, int _w = 2)
std::string toHex(_T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd)
{
std::ostringstream ret;
unsigned ii = 0;
for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
return ret.str();
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
}
/// Converts a (printable) ASCII hex character into the correspnding integer value.
@ -128,9 +133,6 @@ inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toB
inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; }
inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; }
/// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val) { return toHex(toBigEndian(val)); }
/// Convenience function for toBigEndian.
/// @returns a byte array just big enough to represent @a _val.
template <class _T>
@ -150,15 +152,27 @@ inline bytes toCompactBigEndian(byte _val, unsigned _min = 0)
/// Convenience function for toBigEndian.
/// @returns a string just big enough to represent @a _val.
template <class _T>
inline std::string toCompactBigEndianString(_T _val)
inline std::string toCompactBigEndianString(_T _val, unsigned _min = 0)
{
int i = 0;
for (_T v = _val; v; ++i, v >>= 8) {}
std::string ret(i, '\0');
std::string ret(std::max<unsigned>(_min, i), '\0');
toBigEndian(_val, ret);
return ret;
}
/// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
{
std::string str = toHex(toBigEndian(val));
return (prefix == HexPrefix::Add) ? "0x" + str : str;
}
inline std::string toCompactHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd, unsigned _min = 0)
{
std::string str = toHex(toCompactBigEndian(val, _min));
return (prefix == HexPrefix::Add) ? "0x" + str : str;
}
// Algorithms for string and string-like collections.

1
libdevcore/Exceptions.h

@ -51,6 +51,7 @@ struct NoUPnPDevice: virtual Exception {};
struct RootNotFound: virtual Exception {};
struct BadRoot: virtual Exception {};
struct FileError: virtual Exception {};
struct Overflow: virtual Exception {};
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
// error information to be added to exceptions

2
libdevcore/Log.h

@ -181,7 +181,7 @@ protected:
bool m_autospacing = false;
unsigned m_verbosity = 0;
std::stringstream m_sstr; ///< The accrued log entry.
LogTag m_logTag;
LogTag m_logTag = LogTag::None;
};
/// Logging class, iostream-like, that can be shifted to.

6
libdevcrypto/CMakeLists.txt

@ -17,11 +17,7 @@ include_directories(${LEVELDB_INCLUDE_DIRS})
set(EXECUTABLE devcrypto)
file(GLOB HEADERS "*.h")
if(ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})

4
libdevcrypto/Common.cpp

@ -40,8 +40,8 @@ bool dev::SignatureStruct::isValid() const
if (v > 1 ||
r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
s < h256("0x01") ||
r < h256("0x01"))
s < h256(1) ||
r < h256(1))
return false;
return true;
}

4
libethash/CMakeLists.txt

@ -43,3 +43,7 @@ add_library(${LIBRARY} ${FILES})
if (CRYPTOPP_FOUND)
TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES})
endif()
if (NOT ETHASHCL)
install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
endif ()

0
libethereum/ABI.cpp → libethcore/ABI.cpp

8
libethereum/ABI.h → libethcore/ABI.h

@ -31,6 +31,14 @@ namespace dev
namespace eth
{
inline string32 toString32(std::string const& _s)
{
string32 ret;
for (unsigned i = 0; i < 32; ++i)
ret[i] = i < _s.size() ? _s[i] : 0;
return ret;
}
template <class T> struct ABISerialiser {};
template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> const& _t) { static_assert(N <= 32, "Cannot serialise hash > 32 bytes."); static_assert(N > 0, "Cannot serialise zero-length hash."); return bytes(32 - N, 0) + _t.asBytes(); } };
template <> struct ABISerialiser<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } };

6
libethcore/CMakeLists.txt

@ -24,11 +24,7 @@ set(EXECUTABLE ethcore)
file(GLOB HEADERS "*.h")
if(ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} devcrypto)

5
libethcore/Common.cpp

@ -21,6 +21,8 @@
#include "Common.h"
#include <random>
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Base64.h>
#include <libdevcrypto/SHA3.h>
#include "Exceptions.h"
#include "ProofOfWork.h"
@ -100,4 +102,5 @@ std::string formatBalance(bigint const& _b)
return ret.str();
}
}}
}
}

2
libethcore/Common.h

@ -23,6 +23,8 @@
#pragma once
#include <string>
#include <functional>
#include <libdevcore/Common.h>
#include <libdevcore/FixedHash.h>
#include <libdevcrypto/Common.h>

4
libethcore/Ethash.cpp

@ -121,7 +121,7 @@ bool Ethash::verify(BlockInfo const& _header)
return slow;
}
unsigned Ethash::CPUMiner::s_numInstances = 1;
unsigned Ethash::CPUMiner::s_numInstances = 0;
void Ethash::CPUMiner::workLoop()
{
@ -266,7 +266,7 @@ private:
unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 0;
unsigned Ethash::GPUMiner::s_numInstances = 1;
unsigned Ethash::GPUMiner::s_numInstances = 0;
Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
Miner(_ci),

4
libethcore/EthashAux.cpp

@ -64,7 +64,7 @@ ethash_params EthashAux::params(unsigned _n)
h256 EthashAux::seedHash(unsigned _number)
{
unsigned epoch = _number / ETHASH_EPOCH_LENGTH;
RecursiveGuard l(get()->x_this);
Guard l(get()->x_epochs);
if (epoch >= get()->m_seedHashes.size())
{
h256 ret;
@ -87,7 +87,7 @@ h256 EthashAux::seedHash(unsigned _number)
ethash_params EthashAux::params(h256 const& _seedHash)
{
RecursiveGuard l(get()->x_this);
Guard l(get()->x_epochs);
unsigned epoch = 0;
try
{

2
libethcore/EthashAux.h

@ -78,6 +78,8 @@ private:
std::map<h256, std::shared_ptr<LightAllocation>> m_lights;
std::map<h256, std::weak_ptr<FullAllocation>> m_fulls;
FullType m_lastUsedFull;
Mutex x_epochs;
std::map<h256, unsigned> m_epochs;
h256s m_seedHashes;
};

158
libethcore/ICAP.cpp

@ -0,0 +1,158 @@
/*
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 ICAP.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "ICAP.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string.hpp>
#include <libdevcore/Base64.h>
#include <libdevcrypto/SHA3.h>
#include "Exceptions.h"
#include "ABI.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace dev
{
namespace eth
{
string ICAP::iban(std::string _c, std::string _d)
{
boost::to_upper(_c);
boost::to_upper(_d);
auto totStr = _d + _c + "00";
bigint tot = 0;
for (char x: totStr)
if (x >= 'A')
tot = tot * 100 + x - 'A' + 10;
else
tot = tot * 10 + x - '0';
unsigned check = (unsigned)(u256)(98 - tot % 97);
ostringstream out;
out << _c << setfill('0') << setw(2) << check << _d;
return out.str();
}
std::pair<string, string> ICAP::fromIBAN(std::string _iban)
{
if (_iban.size() < 4)
return std::make_pair(string(), string());
boost::to_upper(_iban);
std::string c = _iban.substr(0, 2);
std::string d = _iban.substr(4);
if (iban(c, d) != _iban)
return std::make_pair(string(), string());
return make_pair(c, d);
}
ICAP ICAP::decoded(std::string const& _encoded)
{
ICAP ret;
std::string country;
std::string data;
std::tie(country, data) = fromIBAN(_encoded);
if (country != "XE")
throw InvalidICAP();
if (data.size() == 30)
{
ret.m_type = Direct;
// Direct ICAP
ret.m_direct = fromBase36<Address::size>(data);
}
else if (data.size() == 16)
{
ret.m_type = Indirect;
ret.m_asset = data.substr(0, 3);
if (ret.m_asset == "XET" || ret.m_asset == "ETH")
{
ret.m_institution = data.substr(3, 4);
ret.m_client = data.substr(7);
}
else
throw InvalidICAP();
}
else
throw InvalidICAP();
return ret;
}
std::string ICAP::encoded() const
{
if (m_type == Direct)
{
if (!!m_direct[0])
throw InvalidICAP();
std::string d = toBase36<Address::size>(m_direct);
while (d.size() < 30)
d = "0" + d;
return iban("XE", d);
}
else if (m_type == Indirect)
{
if (
m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos ||
m_asset.size() != 3 ||
(boost::to_upper_copy(m_asset) != "XET" && boost::to_upper_copy(m_asset) != "ETH") ||
m_institution.size() != 4 ||
m_client.size() != 9
)
throw InvalidICAP();
return iban("XE", m_asset + m_institution + m_client);
}
else
throw InvalidICAP();
}
pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const
{
auto resolve = [&](string const& s)
{
vector<string> ss;
boost::algorithm::split(ss, s, boost::is_any_of("/"));
Address r = _reg;
for (unsigned i = 0; i < ss.size() - 1; ++i)
r = abiOut<Address>(_call(r, abiIn("subRegistrar(bytes32)", toString32(ss[i]))));
return abiOut<Address>(_call(r, abiIn("addr(bytes32)", toString32(ss.back()))));
};
if (m_asset == "XET")
{
Address a = resolve(m_institution);
bytes d = abiIn("deposit(uint64)", fromBase36<8>(m_client));
return make_pair(a, d);
}
else if (m_asset == "ETH")
{
if (m_institution == "XREG")
return make_pair(resolve(m_client), bytes());
else if (m_institution[0] != 'X')
return make_pair(resolve(m_institution + "/" + m_client), bytes());
else
throw InterfaceNotSupported("ICAP::lookup(), bad institution");
}
throw InterfaceNotSupported("ICAP::lookup(), bad asset");
}
}
}

107
libethcore/ICAP.h

@ -0,0 +1,107 @@
/*
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 ICAP.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* Ethereum-specific data structures & algorithms.
*/
#pragma once
#include <string>
#include <functional>
#include <boost/algorithm/string/case_conv.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/FixedHash.h>
#include "Common.h"
namespace dev
{
namespace eth
{
struct InvalidICAP: virtual public dev::Exception {};
static const std::string EmptyString;
/**
* @brief Encapsulation of an ICAP address.
* Can be encoded, decoded, looked-up and inspected.
*/
class ICAP
{
public:
/// Construct null ICAP object.
ICAP() = default;
/// Construct a direct ICAP object for given target address. Must have a zero first byte.
ICAP(Address const& _target): m_type(Direct), m_direct(_target) {}
/// Construct an indirect ICAP object for given target name.
ICAP(std::string const& _target): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_target)), m_asset("ETH") {}
/// Construct an indirect ICAP object for given client and institution names.
ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {}
/// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this.
ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_c)), m_institution(boost::algorithm::to_upper_copy(_i)), m_asset(boost::algorithm::to_upper_copy(_a)) {}
/// Type of ICAP address.
enum Type
{
Invalid,
Direct,
Indirect
};
/// @returns IBAN encoding of client and data.
static std::string iban(std::string _c, std::string _d);
/// @returns Client and data from given IBAN address.
static std::pair<std::string, std::string> fromIBAN(std::string _iban);
/// @returns the ICAP object for the ICAP address given.
static ICAP decoded(std::string const& _encoded);
/// @returns the encoded ICAP address.
std::string encoded() const;
/// @returns type of ICAP.
Type type() const { return m_type; }
/// @returns target address. Only valid when type() == Direct.
Address const& direct() const { return m_type == Direct ? m_direct : ZeroAddress; }
/// @returns asset. Only valid when type() == Indirect.
std::string const& asset() const { return m_type == Indirect ? m_asset : EmptyString; }
/// @returns target name. Only valid when type() == Indirect and asset() == "ETH".
std::string const& target() const { return m_type == Indirect && m_asset == "ETH" ? m_client : EmptyString; }
/// @returns institution name. Only valid when type() == Indirect and asset() == "XET".
std::string const& institution() const { return m_type == Indirect && m_asset == "XET" ? m_institution : EmptyString; }
/// @returns client name. Only valid when type() == Indirect and asset() == "XET".
std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; }
/// @returns target address. Always valid, but requires the Registry address and a function to make calls.
std::pair<Address, bytes> address(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { return m_type == Direct ? make_pair(direct(), bytes()) : m_type == Indirect ? lookup(_call, _reg) : make_pair(Address(), bytes()); }
/// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect.
std::pair<Address, bytes> lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const;
private:
Type m_type = Invalid;
Address m_direct;
std::string m_client;
std::string m_institution;
std::string m_asset;
};
}
}

19
libethereum/BlockChain.cpp

@ -336,16 +336,27 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
return make_tuple(fresh, dead, _bq.doneDrain(badBlocks));
}
ImportRoute BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept
pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept
{
try
{
return import(_block, _stateDB, _ir);
return make_pair(ImportResult::Success, import(_block, _stateDB, _ir));
}
catch (UnknownParent&)
{
return make_pair(ImportResult::UnknownParent, make_pair(h256s(), h256s()));
}
catch (AlreadyHaveBlock&)
{
return make_pair(ImportResult::AlreadyKnown, make_pair(h256s(), h256s()));
}
catch (FutureTime&)
{
return make_pair(ImportResult::FutureTime, make_pair(h256s(), h256s()));
}
catch (...)
{
cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information();
return make_pair(h256s(), h256s());
return make_pair(ImportResult::Malformed, make_pair(h256s(), h256s()));
}
}

2
libethereum/BlockChain.h

@ -105,7 +105,7 @@ public:
/// 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.
ImportRoute attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default) noexcept;
std::pair<ImportResult, ImportRoute> attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default) noexcept;
/// Import block into disk-backed DB
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.

6
libethereum/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE ethereum)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} lll)

60
libethereum/Client.cpp

@ -24,6 +24,7 @@
#include <chrono>
#include <thread>
#include <boost/filesystem.hpp>
#include <boost/math/distributions/normal.hpp>
#include <libdevcore/Log.h>
#include <libdevcore/StructuredLogger.h>
#include <libp2p/Host.h>
@ -81,8 +82,10 @@ void BasicGasPricer::update(BlockChain const& _bc)
h256 p = _bc.currentHash();
m_gasPerBlock = _bc.info(p).gasLimit;
map<u256, unsigned> dist;
unsigned total = 0;
map<u256, u256> dist;
u256 total = 0;
// make gasPrice versus gasUsed distribution for the last 1000 blocks
while (c < 1000 && p)
{
BlockInfo bi = _bc.info(p);
@ -91,29 +94,53 @@ void BasicGasPricer::update(BlockChain const& _bc)
auto bb = _bc.block(p);
RLP r(bb);
BlockReceipts brs(_bc.receipts(bi.hash()));
for (unsigned i = 0; i < r[1].size(); ++i)
size_t i = 0;
for (auto const& tr: r[1])
{
auto gu = brs.receipts[i].gasUsed();
dist[Transaction(r[1][i].data(), CheckTransaction::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed();
total += (unsigned)gu;
Transaction tx(tr.data(), CheckTransaction::None);
u256 gu = brs.receipts[i].gasUsed();
dist[tx.gasPrice()] += gu;
total += gu;
i++;
}
}
p = bi.parentHash;
++c;
}
// fill m_octiles with weighted gasPrices
if (total > 0)
{
unsigned t = 0;
unsigned q = 1;
m_octiles[0] = dist.begin()->first;
// calc mean
u256 mean = 0;
for (auto const& i: dist)
mean += i.first * i.second;
mean /= total;
// calc standard deviation
u256 sdSquared = 0;
for (auto const& i: dist)
sdSquared += i.second * (i.first - mean) * (i.first - mean);
sdSquared /= total;
if (sdSquared)
{
for (; t <= total * q / 8 && t + i.second > total * q / 8; ++q)
m_octiles[q] = i.first;
if (q > 7)
break;
long double sd = sqrt(sdSquared.convert_to<long double>());
long double normalizedSd = sd / mean.convert_to<long double>();
// calc octiles normalized to gaussian distribution
boost::math::normal gauss(1.0, (normalizedSd > 0.01) ? normalizedSd : 0.01);
for (size_t i = 1; i < 8; i++)
m_octiles[i] = u256(mean.convert_to<long double>() * boost::math::quantile(gauss, i / 8.0));
m_octiles[8] = dist.rbegin()->first;
}
else
{
for (size_t i = 0; i < 9; i++)
m_octiles[i] = (i + 1) * mean / 5;
}
m_octiles[8] = dist.rbegin()->first;
}
}
@ -671,13 +698,6 @@ eth::State Client::state(unsigned _txi) const
return m_postMine.fromPending(_txi);
}
void Client::inject(bytesConstRef _rlp)
{
startWorking();
m_tq.import(_rlp);
}
void Client::flushTransactions()
{
doWork();

9
libethereum/Client.h

@ -35,12 +35,12 @@
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libethcore/Params.h>
#include <libethcore/ABI.h>
#include <libp2p/Common.h>
#include "CanonBlockChain.h"
#include "TransactionQueue.h"
#include "State.h"
#include "CommonNet.h"
#include "ABI.h"
#include "Farm.h"
#include "ClientBase.h"
@ -77,8 +77,8 @@ class BasicGasPricer: public GasPricer
public:
explicit BasicGasPricer(u256 _weiPerRef, u256 _refsPerBlock): m_weiPerRef(_weiPerRef), m_refsPerBlock(_refsPerBlock) {}
void setRefPrice(u256 _weiPerRef) { m_weiPerRef = _weiPerRef; }
void setRefBlockFees(u256 _refsPerBlock) { m_refsPerBlock = _refsPerBlock; }
void setRefPrice(u256 _weiPerRef) { if ((bigint)m_refsPerBlock * _weiPerRef > std::numeric_limits<u256>::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_weiPerRef = _weiPerRef; }
void setRefBlockFees(u256 _refsPerBlock) { if ((bigint)m_weiPerRef * _refsPerBlock > std::numeric_limits<u256>::max() ) BOOST_THROW_EXCEPTION(Overflow() << errinfo_comment("ether price * block fees is larger than 2**256-1, choose a smaller number.") ); else m_refsPerBlock = _refsPerBlock; }
u256 ask(State const&) const override { return m_weiPerRef * m_refsPerBlock / m_gasPerBlock; }
u256 bid(TransactionPriority _p = TransactionPriority::Medium) const override { return m_octiles[(int)_p] > 0 ? m_octiles[(int)_p] : (m_weiPerRef * m_refsPerBlock / m_gasPerBlock); }
@ -133,9 +133,6 @@ public:
/// Resets the gas pricer to some other object.
void setGasPricer(std::shared_ptr<GasPricer> _gp) { m_gp = _gp; }
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
virtual void inject(bytesConstRef _rlp);
/// Blocks until all pending transactions have been processed.
virtual void flushTransactions() override;

4
libethereum/ClientBase.cpp

@ -114,9 +114,9 @@ ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _da
return ret;
}
void ClientBase::injectBlock(bytes const& _block)
ImportResult ClientBase::injectBlock(bytes const& _block)
{
bc().import(_block, preMine().db());
return bc().attemptImport(_block, preMine().db()).first;
}
u256 ClientBase::balanceAt(Address _a, BlockNumber _block) const

3
libethereum/ClientBase.h

@ -127,7 +127,8 @@ public:
virtual Transactions pending() const override;
virtual h256s pendingHashes() const override;
void injectBlock(bytes const& _block);
ImportResult injectTransaction(bytes const& _rlp) override { prepareForTransaction(); return m_tq.import(_rlp); }
ImportResult injectBlock(bytes const& _block);
using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override;

6
libethereum/Interface.h

@ -85,6 +85,12 @@ public:
virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0;
ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); }
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
virtual ImportResult injectTransaction(bytes const& _rlp) = 0;
/// Injects the RLP-encoded block given by the _rlp into the block queue directly.
virtual ImportResult injectBlock(bytes const& _block) = 0;
// [STATE-QUERY API]
int getDefault() const { return m_default; }

2
libethereum/Transaction.cpp

@ -105,7 +105,7 @@ Address const& Transaction::safeSender() const noexcept
catch (...)
{
cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information();
return NullAddress;
return ZeroAddress;
}
}

8
libethereum/Transaction.h

@ -97,8 +97,6 @@ struct ExecutionResult
std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er);
static const Address NullAddress;
/// Encodes a transaction, ready to be exported to or freshly imported from RLP.
class Transaction
{
@ -167,6 +165,12 @@ public:
/// @returns the receiving address of the message-call transaction (undefined for contract-creation transactions).
Address receiveAddress() const { return m_receiveAddress; }
/// Synonym for receiveAddress().
Address to() const { return m_receiveAddress; }
/// Synonym for safeSender().
Address from() const { return safeSender(); }
/// @returns the data associated with this (message-call) transaction. Synonym for initCode().
bytes const& data() const { return m_data; }
/// @returns the initialisation code associated with this (contract-creation) transaction. Synonym for data().

6
libethereumx/CMakeLists.txt

@ -11,11 +11,7 @@ set(EXECUTABLE ethereumx)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${LEVELDB_LS})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS})

6
libevm/CMakeLists.txt

@ -20,11 +20,7 @@ set(EXECUTABLE evm)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)

13
libevmcore/AssemblyItem.h

@ -43,9 +43,16 @@ class AssemblyItem
public:
enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
AssemblyItem(u256 _push): m_type(Push), m_data(_push) {}
AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {}
AssemblyItem(AssemblyItemType _type, u256 _data = 0): m_type(_type), m_data(_data) {}
AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Push, _push, _location) { }
AssemblyItem(Instruction _i, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Operation, byte(_i), _location) { }
AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()):
m_type(_type),
m_data(_data),
m_location(_location)
{
}
AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); }
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); }

6
libevmcore/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE evmcore)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} devcrypto)

176
libevmcore/CommonSubexpressionEliminator.cpp

@ -41,9 +41,9 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
if (!m_stackElements.empty())
minHeight = min(minHeight, m_stackElements.begin()->first);
for (int height = minHeight; height <= 0; ++height)
initialStackContents[height] = initialStackElement(height);
initialStackContents[height] = initialStackElement(height, SourceLocation());
for (int height = minHeight; height <= m_stackHeight; ++height)
targetStackContents[height] = stackElement(height);
targetStackContents[height] = stackElement(height, SourceLocation());
// Debug info:
//stream(cout, initialStackContents, targetStackContents);
@ -111,30 +111,46 @@ void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item, bool _co
if (SemanticInformation::isDupInstruction(_item))
setStackElement(
m_stackHeight + 1,
stackElement(m_stackHeight - int(instruction) + int(Instruction::DUP1))
stackElement(
m_stackHeight - int(instruction) + int(Instruction::DUP1),
_item.getLocation()
)
);
else if (SemanticInformation::isSwapInstruction(_item))
swapStackElements(
m_stackHeight,
m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1)
m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1),
_item.getLocation()
);
else if (instruction != Instruction::POP)
{
vector<Id> arguments(info.args);
for (int i = 0; i < info.args; ++i)
arguments[i] = stackElement(m_stackHeight - i);
arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
if (_item.instruction() == Instruction::SSTORE)
storeInStorage(arguments[0], arguments[1]);
storeInStorage(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::SLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromStorage(arguments[0]));
setStackElement(
m_stackHeight + _item.deposit(),
loadFromStorage(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::MSTORE)
storeInMemory(arguments[0], arguments[1]);
storeInMemory(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::MLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromMemory(arguments[0]));
setStackElement(
m_stackHeight + _item.deposit(),
loadFromMemory(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::SHA3)
setStackElement(m_stackHeight + _item.deposit(), applySha3(arguments.at(0), arguments.at(1)));
setStackElement(
m_stackHeight + _item.deposit(),
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
);
else
setStackElement(m_stackHeight + _item.deposit(), m_expressionClasses.find(_item, arguments, _copyItem));
setStackElement(
m_stackHeight + _item.deposit(),
m_expressionClasses.find(_item, arguments, _copyItem)
);
}
m_stackHeight += _item.deposit();
}
@ -145,22 +161,27 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
if (!m_breakingItem || *m_breakingItem != AssemblyItem(Instruction::JUMPI))
return;
static AssemblyItem s_jump = Instruction::JUMP;
SourceLocation const& location = m_breakingItem->getLocation();
AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType();
Id condition = stackElement(m_stackHeight - 1);
Id condition = stackElement(m_stackHeight - 1, location);
Id zero = m_expressionClasses.find(u256(0));
if (m_expressionClasses.knownToBeDifferent(condition, zero))
{
feedItem(Instruction::SWAP1, true);
feedItem(Instruction::POP, true);
m_breakingItem = &s_jump;
feedItem(AssemblyItem(Instruction::SWAP1, location), true);
feedItem(AssemblyItem(Instruction::POP, location), true);
AssemblyItem item(Instruction::JUMP, location);
item.setJumpType(jumpType);
m_breakingItem = m_expressionClasses.storeItem(item);
return;
}
Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition});
if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero))
{
feedItem(Instruction::POP, true);
feedItem(Instruction::POP, true);
AssemblyItem it(Instruction::POP, location);
feedItem(it, true);
feedItem(it, true);
m_breakingItem = nullptr;
}
}
@ -170,33 +191,43 @@ void CommonSubexpressionEliminator::setStackElement(int _stackHeight, Id _class)
m_stackElements[_stackHeight] = _class;
}
void CommonSubexpressionEliminator::swapStackElements(int _stackHeightA, int _stackHeightB)
void CommonSubexpressionEliminator::swapStackElements(
int _stackHeightA,
int _stackHeightB,
SourceLocation const& _location
)
{
assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements.");
// ensure they are created
stackElement(_stackHeightA);
stackElement(_stackHeightB);
stackElement(_stackHeightA, _location);
stackElement(_stackHeightB, _location);
swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
}
ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(int _stackHeight)
ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(
int _stackHeight,
SourceLocation const& _location
)
{
if (m_stackElements.count(_stackHeight))
return m_stackElements.at(_stackHeight);
// Stack element not found (not assigned yet), create new equivalence class.
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight);
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
}
ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(int _stackHeight)
ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(
int _stackHeight,
SourceLocation const& _location
)
{
assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested.");
assertThrow(_stackHeight > -16, StackTooDeepException, "");
// This is a special assembly item that refers to elements pre-existing on the initial stack.
return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight)));
return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight), _location));
}
void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value)
void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value, SourceLocation const& _location)
{
if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value)
// do not execute the storage if we know that the value is already there
@ -210,22 +241,25 @@ void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value)
storageContents.insert(storageItem);
m_storageContent = move(storageContents);
Id id = m_expressionClasses.find(Instruction::SSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::SSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id));
m_storageContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++;
}
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot)
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot, SourceLocation const& _location)
{
if (m_storageContent.count(_slot))
return m_storageContent.at(_slot);
else
return m_storageContent[_slot] = m_expressionClasses.find(Instruction::SLOAD, {_slot}, true, m_sequenceNumber);
AssemblyItem item(Instruction::SLOAD, _location);
return m_storageContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
}
void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value)
void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value, SourceLocation const& _location)
{
if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value)
// do not execute the store if we know that the value is already there
@ -237,34 +271,45 @@ void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot))
memoryContents.insert(memoryItem);
m_memoryContent = move(memoryContents);
Id id = m_expressionClasses.find(Instruction::MSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::MSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id));
m_memoryContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++;
}
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot)
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot, SourceLocation const& _location)
{
if (m_memoryContent.count(_slot))
return m_memoryContent.at(_slot);
else
return m_memoryContent[_slot] = m_expressionClasses.find(Instruction::MLOAD, {_slot}, true, m_sequenceNumber);
AssemblyItem item(Instruction::MLOAD, _location);
return m_memoryContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
}
CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _start, Id _length)
CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(
Id _start,
Id _length,
SourceLocation const& _location
)
{
AssemblyItem sha3Item(Instruction::SHA3, _location);
// Special logic if length is a short constant, otherwise we cannot tell.
u256 const* l = m_expressionClasses.knownConstant(_length);
// unknown or too large length
if (!l || *l > 128)
return m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber);
return m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
vector<Id> arguments;
for (u256 i = 0; i < *l; i += 32)
{
Id slot = m_expressionClasses.find(Instruction::ADD, {_start, m_expressionClasses.find(i)});
arguments.push_back(loadFromMemory(slot));
Id slot = m_expressionClasses.find(
AssemblyItem(Instruction::ADD, _location),
{_start, m_expressionClasses.find(i)}
);
arguments.push_back(loadFromMemory(slot, _location));
}
if (m_knownSha3Hashes.count(arguments))
return m_knownSha3Hashes.at(arguments);
@ -276,10 +321,10 @@ CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _s
for (Id a: arguments)
data += toBigEndian(*m_expressionClasses.knownConstant(a));
data.resize(size_t(*l));
v = m_expressionClasses.find(u256(sha3(data)));
v = m_expressionClasses.find(AssemblyItem(u256(sha3(data)), _location));
}
else
v = m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber);
v = m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
return m_knownSha3Hashes[arguments] = v;
}
@ -333,12 +378,13 @@ AssemblyItems CSECodeGenerator::generateCode(
assertThrow(position != c_invalidPosition, OptimizerException, "");
if (position == targetItem.first)
continue;
SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation();
if (position < targetItem.first)
// it is already at its target, we need another copy
appendDup(position);
appendDup(position, location);
else
appendOrRemoveSwap(position);
appendOrRemoveSwap(targetItem.first);
appendOrRemoveSwap(position, location);
appendOrRemoveSwap(targetItem.first, location);
}
// remove surplus elements
@ -404,7 +450,8 @@ void CSECodeGenerator::addDependencies(Id _c)
case Instruction::SHA3:
{
Id length = expr.arguments.at(1);
Id offsetToStart = m_expressionClasses.find(Instruction::SUB, {slot, slotToLoadFrom});
AssemblyItem offsetInstr(Instruction::SUB, expr.item->getLocation());
Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom});
u256 const* o = m_expressionClasses.knownConstant(offsetToStart);
u256 const* l = m_expressionClasses.knownConstant(length);
if (l && *l == 0)
@ -462,6 +509,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
for (Id arg: boost::adaptors::reverse(arguments))
generateClassElement(arg);
SourceLocation const& location = expr.item->getLocation();
// The arguments are somewhere on the stack now, so it remains to move them at the correct place.
// This is quite difficult as sometimes, the values also have to removed in this process
// (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is
@ -469,42 +517,42 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
if (arguments.size() == 1)
{
if (canBeRemoved(arguments[0], _c))
appendOrRemoveSwap(classElementPosition(arguments[0]));
appendOrRemoveSwap(classElementPosition(arguments[0]), location);
else
appendDup(classElementPosition(arguments[0]));
appendDup(classElementPosition(arguments[0]), location);
}
else if (arguments.size() == 2)
{
if (canBeRemoved(arguments[1], _c))
{
appendOrRemoveSwap(classElementPosition(arguments[1]));
appendOrRemoveSwap(classElementPosition(arguments[1]), location);
if (arguments[0] == arguments[1])
appendDup(m_stackHeight);
appendDup(m_stackHeight, location);
else if (canBeRemoved(arguments[0], _c))
{
appendOrRemoveSwap(m_stackHeight - 1);
appendOrRemoveSwap(classElementPosition(arguments[0]));
appendOrRemoveSwap(m_stackHeight - 1, location);
appendOrRemoveSwap(classElementPosition(arguments[0]), location);
}
else
appendDup(classElementPosition(arguments[0]));
appendDup(classElementPosition(arguments[0]), location);
}
else
{
if (arguments[0] == arguments[1])
{
appendDup(classElementPosition(arguments[0]));
appendDup(m_stackHeight);
appendDup(classElementPosition(arguments[0]), location);
appendDup(m_stackHeight, location);
}
else if (canBeRemoved(arguments[0], _c))
{
appendOrRemoveSwap(classElementPosition(arguments[0]));
appendDup(classElementPosition(arguments[1]));
appendOrRemoveSwap(m_stackHeight - 1);
appendOrRemoveSwap(classElementPosition(arguments[0]), location);
appendDup(classElementPosition(arguments[1]), location);
appendOrRemoveSwap(m_stackHeight - 1, location);
}
else
{
appendDup(classElementPosition(arguments[1]));
appendDup(classElementPosition(arguments[0]));
appendDup(classElementPosition(arguments[1]), location);
appendDup(classElementPosition(arguments[0]), location);
}
}
}
@ -521,7 +569,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
!m_generatedItems.empty() &&
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
// this will not append a swap but remove the one that is already there
appendOrRemoveSwap(m_stackHeight - 1);
appendOrRemoveSwap(m_stackHeight - 1, location);
for (auto arg: arguments)
if (canBeRemoved(arg, _c))
m_classPositions[arg] = c_invalidPosition;
@ -582,17 +630,17 @@ bool CSECodeGenerator::removeStackTopIfPossible()
return true;
}
void CSECodeGenerator::appendDup(int _fromPosition)
void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location)
{
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
int instructionNum = 1 + m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(dupInstruction(instructionNum)));
appendItem(AssemblyItem(dupInstruction(instructionNum), _location));
m_stack[m_stackHeight] = m_stack[_fromPosition];
}
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition)
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location)
{
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
if (_fromPosition == m_stackHeight)
@ -600,7 +648,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition)
int instructionNum = m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(swapInstruction(instructionNum)));
appendItem(AssemblyItem(swapInstruction(instructionNum), _location));
// The value of a class can be present in multiple locations on the stack. We only update the
// "canonical" one that is tracked by m_classPositions
if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight)

20
libevmcore/CommonSubexpressionEliminator.h

@ -99,26 +99,26 @@ private:
/// Assigns a new equivalence class to the next sequence number of the given stack element.
void setStackElement(int _stackHeight, Id _class);
/// Swaps the given stack elements in their next sequence number.
void swapStackElements(int _stackHeightA, int _stackHeightB);
void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location);
/// Retrieves the current equivalence class fo the given stack element (or generates a new
/// one if it does not exist yet).
Id stackElement(int _stackHeight);
Id stackElement(int _stackHeight, SourceLocation const& _location);
/// @returns the equivalence class id of the special initial stack element at the given height
/// (must not be positive).
Id initialStackElement(int _stackHeight);
Id initialStackElement(int _stackHeight, SourceLocation const& _location);
/// Increments the sequence number, deletes all storage information that might be overwritten
/// and stores the new value at the given slot.
void storeInStorage(Id _slot, Id _value);
void storeInStorage(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in storage or creates a new special sload class.
Id loadFromStorage(Id _slot);
Id loadFromStorage(Id _slot, SourceLocation const& _location);
/// Increments the sequence number, deletes all memory information that might be overwritten
/// and stores the new value at the given slot.
void storeInMemory(Id _slot, Id _value);
void storeInMemory(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in memory or creates a new special mload class.
Id loadFromMemory(Id _slot);
Id loadFromMemory(Id _slot, SourceLocation const& _location);
/// Finds or creates a new expression that applies the sha3 hash function to the contents in memory.
Id applySha3(Id _start, Id _length);
Id applySha3(Id _start, Id _length, SourceLocation const& _location);
/// Current stack height, can be negative.
int m_stackHeight = 0;
@ -188,10 +188,10 @@ private:
bool removeStackTopIfPossible();
/// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position.
void appendDup(int _fromPosition);
void appendDup(int _fromPosition, SourceLocation const& _location);
/// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position.
/// @note this might also remove the last item if it exactly the same swap instruction.
void appendOrRemoveSwap(int _fromPosition);
void appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location);
/// Appends the given assembly item.
void appendItem(AssemblyItem const& _item);

24
libevmcore/ExpressionClasses.cpp

@ -64,10 +64,7 @@ ExpressionClasses::Id ExpressionClasses::find(
return it->id;
if (_copyItem)
{
m_spareAssemblyItem.push_back(make_shared<AssemblyItem>(_item));
exp.item = m_spareAssemblyItem.back().get();
}
exp.item = storeItem(_item);
ExpressionClasses::Id id = tryToSimplify(exp);
if (id < m_representatives.size())
@ -115,6 +112,12 @@ u256 const* ExpressionClasses::knownConstant(Id _c)
return &constant.d();
}
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
{
m_spareAssemblyItems.push_back(make_shared<AssemblyItem>(_item));
return m_spareAssemblyItems.back().get();
}
string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
{
Expression const& expr = representative(_id);
@ -292,7 +295,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
//cout << "with rule " << rule.first.toString() << endl;
//ExpressionTemplate t(rule.second());
//cout << "to " << rule.second().toString() << endl;
return rebuildExpression(ExpressionTemplate(rule.second()));
return rebuildExpression(ExpressionTemplate(rule.second(), _expr.item->getLocation()));
}
}
@ -350,6 +353,11 @@ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes
return true;
}
AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
{
return AssemblyItem(m_type, m_data, _location);
}
string Pattern::toString() const
{
stringstream s;
@ -399,7 +407,7 @@ Pattern::Expression const& Pattern::matchGroupValue() const
}
ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern)
ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location)
{
if (_pattern.matchGroup())
{
@ -409,10 +417,10 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern)
else
{
hasId = false;
item = _pattern.toAssemblyItem();
item = _pattern.toAssemblyItem(_location);
}
for (auto const& arg: _pattern.arguments())
arguments.push_back(ExpressionTemplate(arg));
arguments.push_back(ExpressionTemplate(arg, _location));
}
string ExpressionTemplate::toString() const

10
libevmcore/ExpressionClasses.h

@ -88,6 +88,10 @@ public:
/// and a nullptr otherwise.
u256 const* knownConstant(Id _c);
/// Stores a copy of the given AssemblyItem and returns a pointer to the copy that is valid for
/// the lifetime of the ExpressionClasses object.
AssemblyItem const* storeItem(AssemblyItem const& _item);
std::string fullDAGToString(Id _id) const;
private:
@ -105,7 +109,7 @@ private:
std::vector<Expression> m_representatives;
/// All expression ever encountered.
std::set<Expression> m_expressions;
std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItem;
std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItems;
};
/**
@ -134,7 +138,7 @@ public:
unsigned matchGroup() const { return m_matchGroup; }
bool matches(Expression const& _expr, ExpressionClasses const& _classes) const;
AssemblyItem toAssemblyItem() const { return AssemblyItem(m_type, m_data); }
AssemblyItem toAssemblyItem(SourceLocation const& _location) const;
std::vector<Pattern> arguments() const { return m_arguments; }
/// @returns the id of the matched expression if this pattern is part of a match group.
@ -163,7 +167,7 @@ struct ExpressionTemplate
{
using Expression = ExpressionClasses::Expression;
using Id = ExpressionClasses::Id;
explicit ExpressionTemplate(Pattern const& _pattern);
explicit ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location);
std::string toString() const;
bool hasId = false;
/// Id of the matched expression, if available.

1
libjsqrc/ethereumjs/.travis.yml

@ -2,7 +2,6 @@ language: node_js
node_js:
- "0.12"
- "0.11"
- "0.10"
before_script:
- npm install
- npm install jshint

34
libjsqrc/ethereumjs/README.md

@ -1,6 +1,6 @@
# Ethereum JavaScript API
[![Join the chat at https://gitter.im/ethereum/ethereum.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/ethereum.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join the chat at https://gitter.im/ethereum/web3.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/web3.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
This is the Ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API)
which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) spec. It's available on npm as a node module, for bower and component as an embeddable js and as a meteor.js package.
@ -21,7 +21,7 @@ You need to run a local ethrereum node to use this library.
### Meteor.js
$ meteor add ethereum:js
$ meteor add ethereum:web3
### As Browser module
Bower
@ -36,11 +36,7 @@ Component
* Include [bignumber.js](https://github.com/MikeMcl/bignumber.js/) (not required for the meteor package)
## Usage
You can require the library (not required for the meteor package):
var web3 = require('ethereum.js');
Or use it directly from global namespace:
Use the `web3` object directly from global namespace:
console.log(web3); // {eth: .., shh: ...} // it's here!
@ -106,16 +102,16 @@ Install ethereum and spawn a node:
eth -j
```
[npm-image]: https://badge.fury.io/js/ethereum.js.png
[npm-url]: https://npmjs.org/package/ethereum.js
[travis-image]: https://travis-ci.org/ethereum/ethereum.js.svg
[travis-url]: https://travis-ci.org/ethereum/ethereum.js
[dep-image]: https://david-dm.org/ethereum/ethereum.js.svg
[dep-url]: https://david-dm.org/ethereum/ethereum.js
[dep-dev-image]: https://david-dm.org/ethereum/ethereum.js/dev-status.svg
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies
[coveralls-image]: https://coveralls.io/repos/ethereum/ethereum.js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/r/ethereum/ethereum.js?branch=master
[waffle-image]: https://badge.waffle.io/ethereum/ethereum.js.svg?label=ready&title=Ready
[waffle-url]: http://waffle.io/ethereum/ethereum.js
[npm-image]: https://badge.fury.io/js/web3.png
[npm-url]: https://npmjs.org/package/web3
[travis-image]: https://travis-ci.org/ethereum/web3.js.svg
[travis-url]: https://travis-ci.org/ethereum/web3.js
[dep-image]: https://david-dm.org/ethereum/web3.js.svg
[dep-url]: https://david-dm.org/ethereum/web3.js
[dep-dev-image]: https://david-dm.org/ethereum/web.js/dev-status.svg
[dep-dev-url]: https://david-dm.org/ethereum/web3.js#info=devDependencies
[coveralls-image]: https://coveralls.io/repos/ethereum/web3.js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/r/ethereum/web3.js?branch=master
[waffle-image]: https://badge.waffle.io/ethereum/web3.js.svg?label=ready&title=Ready
[waffle-url]: http://waffle.io/ethereum/web3.js

2
libjsqrc/ethereumjs/bower.json

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

1644
libjsqrc/ethereumjs/dist/web3-light.js

File diff suppressed because it is too large

46
libjsqrc/ethereumjs/dist/web3-light.js.map

File diff suppressed because one or more lines are too long

3
libjsqrc/ethereumjs/dist/web3-light.min.js

File diff suppressed because one or more lines are too long

6998
libjsqrc/ethereumjs/dist/web3.js

File diff suppressed because it is too large

50
libjsqrc/ethereumjs/dist/web3.js.map

File diff suppressed because one or more lines are too long

4
libjsqrc/ethereumjs/dist/web3.min.js

File diff suppressed because one or more lines are too long

57
libjsqrc/ethereumjs/example/contract.html

@ -2,36 +2,34 @@
<html>
<head>
<script type="text/javascript" src="../dist/web3"></script>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider());
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));
// solidity source code
var source = "" +
"contract test {\n" +
" function multiply(uint a) returns(uint d) {\n" +
" return a * 7;\n" +
" }\n" +
"}\n";
/*var source = "" +*/
/*"contract test {\n" +*/
/*" function multiply(uint a) constant returns(uint d) {\n" +*/
/*" return a * 7;\n" +*/
/*" }\n" +*/
/*"}\n";*/
var source = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056";
// contract description, this will be autogenerated somehow
var desc = [{
"name": "multiply(uint256)",
"type": "function",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
// contract description, this is autogenerated using solc CLI
var desc = [{
"constant" : true,
"inputs" : [{
"name" : "a",
"type" : "uint256"
}],
"name" : "multiply",
"outputs" : [{
"name" : "d",
"type" : "uint256"
}],
"type" : "function"
}];
var myContract;
@ -41,11 +39,12 @@
document.getElementById('create').style.visibility = 'hidden';
document.getElementById('source').innerText = source;
// create contract
var address = web3.eth.sendTransaction({data: web3.eth.compile.solidity(source)}),
Contract = web3.eth.contract(desc);
// let's assume that coinbase is our account
web3.eth.defaultAccount = web3.eth.coinbase;
myContract = new Contract(address);
// create contract
var Contract = web3.eth.contract(desc);
myContract = new Contract({data: source});
document.getElementById('call').style.visibility = 'visible';
}
@ -54,7 +53,7 @@
var param = parseInt(document.getElementById('value').value);
// call the contract
var res = myContract.call().multiply(param);
var res = myContract.multiply(param);
document.getElementById('result').innerText = res.toString(10);
}

77
libjsqrc/ethereumjs/example/contract_with_array.html

@ -1,77 +0,0 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider());
// solidity source code
var source = "" +
"contract test {\n" +
" function multiply(uint[] a) returns(uint d) {\n" +
" return a[0] + a[1];\n" +
" }\n" +
"}\n";
// contract description, this will be autogenerated somehow
var desc = [{
"name": "multiply(uint256[])",
"type": "function",
"inputs": [
{
"name": "a",
"type": "uint256[]"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}];
var myContract;
function createExampleContract() {
// hide create button
document.getElementById('create').style.visibility = 'hidden';
document.getElementById('source').innerText = source;
// create contract
var address = web3.eth.sendTransaction({data: web3.eth.compile.solidity(source)}),
Contract = web3.eth.contract(desc);
myContract = new Contract(address);
document.getElementById('call').style.visibility = 'visible';
}
function callExampleContract() {
// this should be generated by ethereum
var param = parseInt(document.getElementById('value').value);
var param2 = parseInt(document.getElementById('value2').value);
// call the contract
var res = myContract.call().multiply([param, param2]);
document.getElementById('result').innerText = res.toString(10);
}
</script>
</head>
<body>
<h1>contract</h1>
<div id="source"></div>
<div id='create'>
<button type="button" onClick="createExampleContract();">create example contract</button>
</div>
<div id='call' style='visibility: hidden;'>
<input type="number" id="value" onkeyup='callExampleContract()'></input>
<input type="number" id="value2" onkeyup='callExampleContract()'></input>
</div>
<div id="result"></div>
</body>
</html>

119
libjsqrc/ethereumjs/example/event.html

@ -1,119 +0,0 @@
<!doctype>
<html>
<head>
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));
var desc = [{
"type":"event",
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}],
"name":"Event"
}, {
"type":"event",
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"hash256","indexed":false}],
"name":"Event2"
}, {
"type":"function",
"inputs": [{"name":"a","type":"uint256"}],
"name":"foo",
"outputs": []
}];
var address = '0x01';
var contract = web3.eth.contract(address, desc);
function test1() {
// "{"topic":["0x83c9849c","0xc4d76332"],"address":"0x01"}"
web3.eth.watch(contract).changed(function (res) {
});
};
function test2() {
// "{"topic":["0x83c9849c"],"address":"0x01"}"
web3.eth.watch(contract.Event).changed(function (res) {
});
};
function test3() {
// "{"topic":["0x83c9849c"],"address":"0x01"}"
contract.Event().changed(function (res) {
});
};
function test4() {
// "{"topic":["0x83c9849c","0000000000000000000000000000000000000000000000000000000000000045"],"address":"0x01"}"
contract.Event({a: 69}).changed(function (res) {
});
};
function test5() {
// "{"topic":["0x83c9849c",["0000000000000000000000000000000000000000000000000000000000000045","000000000000000000000000000000000000000000000000000000000000002a"]],"address":"0x01"}"
contract.Event({a: [69, 42]}).changed(function (res) {
});
};
function test6() {
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}"
contract.Event({a: 30}, {max: 100}).changed(function (res) {
});
};
function test7() {
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"address":"0x01"}"
web3.eth.watch(contract.Event, {a: 30}).changed(function (res) {
});
};
function test8() {
// "{"topic":["0x83c9849c","000000000000000000000000000000000000000000000000000000000000001e"],"max":100,"address":"0x01"}"
web3.eth.watch(contract.Event, {a: 30}, {max: 100}).changed(function (res) {
});
};
// not valid
// function testX() {
// web3.eth.watch([contract.Event, contract.Event2]).changed(function (res) {
// });
// };
</script>
</head>
<body>
<div>
<button type="button" onClick="test1();">test1</button>
</div>
<div>
<button type="button" onClick="test2();">test2</button>
</div>
<div>
<button type="button" onClick="test3();">test3</button>
</div>
<div>
<button type="button" onClick="test4();">test4</button>
</div>
<div>
<button type="button" onClick="test5();">test5</button>
</div>
<div>
<button type="button" onClick="test6();">test6</button>
</div>
<div>
<button type="button" onClick="test7();">test7</button>
</div>
<div>
<button type="button" onClick="test8();">test8</button>
</div>
</body>
</html>

65
libjsqrc/ethereumjs/example/event_inc.html

@ -4,48 +4,61 @@
<script type="text/javascript" src="../dist/web3.js"></script>
<script type="text/javascript">
var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080'));
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
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 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 source = "5b60456000600050819055505b608c8060196000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063371303c014602e57005b6034603a565b60006000f35b6000600081815054600101919050819055506001600260006000505406147f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad600060006000505481526020016000a25b56";
var desc = [{
"type":"event",
"name":"Incremented",
"inputs": [{"name":"odd","type":"bool","indexed":true},{"name":"x","type":"uint","indexed":false}],
"constant" : false,
"inputs" : [],
"name" : "inc",
"outputs" : [],
"type" : "function"
}, {
"type":"function",
"name":"inc",
"inputs": [],
"outputs": []
"anonymous" : false,
"inputs" : [{
"indexed" : true,
"name" : "odd",
"type" : "bool"
}, {
"indexed" : false,
"name" : "x",
"type" : "uint256"
}],
"name" : "Incremented",
"type" : "event"
}];
var address;
var contract;
var update = function (x) {
document.getElementById('result').innerText = JSON.stringify(x);
var update = function (err, x) {
document.getElementById('result').innerText = JSON.stringify(x, null, 2);
};
var createContract = function () {
address = web3.eth.sendTransaction({data: web3.eth.compile.solidity(source)});
contract = web3.eth.contract(address, desc);
contract.Incremented({odd: true}).changed(update);
// let's assume that we have a private key to coinbase ;)
web3.eth.defaultAccount = web3.eth.coinbase;
var Contract = web3.eth.contract(desc);
contract = new Contract({data: source});
contract.Incremented({odd: true}).watch(update);
};
var callContract = function () {
contract.call().inc();
contract.inc();
};

143
libjsqrc/ethereumjs/lib/solidity/abi.js

@ -22,49 +22,9 @@
*/
var utils = require('../utils/utils');
var c = require('../utils/config');
var types = require('./types');
var f = require('./formatters');
var coder = require('./coder');
var solUtils = require('./utils');
/**
* throw incorrect type error
*
* @method throwTypeError
* @param {String} type
* @throws incorrect type error
*/
var throwTypeError = function (type) {
throw new Error('parser does not support type: ' + type);
};
/** This method should be called if we want to check if givent type is an array type
*
* @method isArrayType
* @param {String} type name
* @returns {Boolean} true if it is, otherwise false
*/
var isArrayType = function (type) {
return type.slice(-2) === '[]';
};
/**
* This method should be called to return dynamic type length in hex
*
* @method dynamicTypeBytes
* @param {String} type
* @param {String|Array} dynamic type
* @return {String} length of dynamic type in hex or empty string if type is not dynamic
*/
var dynamicTypeBytes = function (type, value) {
// TODO: decide what to do with array of strings
if (isArrayType(type) || type === 'bytes')
return f.formatInputInt(value.length);
return "";
};
var inputTypes = types.inputTypes();
/**
* Formats input params to bytes
*
@ -74,57 +34,12 @@ var inputTypes = types.inputTypes();
* @returns bytes representation of input params
*/
var formatInput = function (inputs, params) {
var bytes = "";
var toAppendConstant = "";
var toAppendArrayContent = "";
/// first we iterate in search for dynamic
inputs.forEach(function (input, index) {
bytes += dynamicTypeBytes(input.type, params[index]);
var i = inputs.map(function (input) {
return input.type;
});
inputs.forEach(function (input, i) {
/*jshint maxcomplexity:5 */
var typeMatch = false;
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
typeMatch = inputTypes[j].type(inputs[i].type, params[i]);
}
if (!typeMatch) {
throwTypeError(inputs[i].type);
}
var formatter = inputTypes[j - 1].format;
if (isArrayType(inputs[i].type))
toAppendArrayContent += params[i].reduce(function (acc, curr) {
return acc + formatter(curr);
}, "");
else if (inputs[i].type === 'bytes')
toAppendArrayContent += formatter(params[i]);
else
toAppendConstant += formatter(params[i]);
});
bytes += toAppendConstant + toAppendArrayContent;
return bytes;
};
/**
* This method should be called to predict the length of dynamic type
*
* @method dynamicBytesLength
* @param {String} type
* @returns {Number} length of dynamic type, 0 or multiplication of ETH_PADDING (32)
*/
var dynamicBytesLength = function (type) {
if (isArrayType(type) || type === 'bytes')
return c.ETH_PADDING * 2;
return 0;
return coder.encodeParams(i, params);
};
var outputTypes = types.outputTypes();
/**
* Formats output bytes back to param list
*
@ -133,52 +48,12 @@ var outputTypes = types.outputTypes();
* @param {String} bytes represention of output
* @returns {Array} output params
*/
var formatOutput = function (outs, output) {
output = output.slice(2);
var result = [];
var padding = c.ETH_PADDING * 2;
var dynamicPartLength = outs.reduce(function (acc, curr) {
return acc + dynamicBytesLength(curr.type);
}, 0);
var dynamicPart = output.slice(0, dynamicPartLength);
output = output.slice(dynamicPartLength);
outs.forEach(function (out, i) {
/*jshint maxcomplexity:6 */
var typeMatch = false;
for (var j = 0; j < outputTypes.length && !typeMatch; j++) {
typeMatch = outputTypes[j].type(outs[i].type);
}
if (!typeMatch) {
throwTypeError(outs[i].type);
}
var formatter = outputTypes[j - 1].format;
if (isArrayType(outs[i].type)) {
var size = f.formatOutputUInt(dynamicPart.slice(0, padding));
dynamicPart = dynamicPart.slice(padding);
var array = [];
for (var k = 0; k < size; k++) {
array.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
result.push(array);
}
else if (types.prefixedType('bytes')(outs[i].type)) {
dynamicPart = dynamicPart.slice(padding);
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
} else {
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
var formatOutput = function (outs, bytes) {
var o = outs.map(function (out) {
return out.type;
});
return result;
return coder.decodeParams(o, bytes);
};
/**

329
libjsqrc/ethereumjs/lib/solidity/coder.js

@ -0,0 +1,329 @@
/*
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 coder.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var BigNumber = require('bignumber.js');
var utils = require('../utils/utils');
var f = require('./formatters');
var SolidityParam = require('./param');
/**
* Should be used to check if a type is an array type
*
* @method isArrayType
* @param {String} type
* @return {Bool} true is the type is an array, otherwise false
*/
var isArrayType = function (type) {
return type.slice(-2) === '[]';
};
/**
* SolidityType prototype is used to encode/decode solidity params of certain type
*/
var SolidityType = function (config) {
this._name = config.name;
this._match = config.match;
this._mode = config.mode;
this._inputFormatter = config.inputFormatter;
this._outputFormatter = config.outputFormatter;
};
/**
* Should be used to determine if this SolidityType do match given type
*
* @method isType
* @param {String} name
* @return {Bool} true if type match this SolidityType, otherwise false
*/
SolidityType.prototype.isType = function (name) {
if (this._match === 'strict') {
return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');
} else if (this._match === 'prefix') {
// TODO better type detection!
return name.indexOf(this._name) === 0;
}
};
/**
* Should be used to transform plain param to SolidityParam object
*
* @method formatInput
* @param {Object} param - plain object, or an array of objects
* @param {Bool} arrayType - true if a param should be encoded as an array
* @return {SolidityParam} encoded param wrapped in SolidityParam object
*/
SolidityType.prototype.formatInput = function (param, arrayType) {
if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same
var self = this;
return param.map(function (p) {
return self._inputFormatter(p);
}).reduce(function (acc, current) {
acc.appendArrayElement(current);
return acc;
}, new SolidityParam('', f.formatInputInt(param.length).value));
}
return this._inputFormatter(param);
};
/**
* Should be used to transoform SolidityParam to plain param
*
* @method formatOutput
* @param {SolidityParam} byteArray
* @param {Bool} arrayType - true if a param should be decoded as an array
* @return {Object} plain decoded param
*/
SolidityType.prototype.formatOutput = function (param, arrayType) {
if (arrayType) {
// let's assume, that we solidity will never return long arrays :P
var result = [];
var length = new BigNumber(param.prefix, 16);
for (var i = 0; i < length * 64; i += 64) {
result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64))));
}
return result;
}
return this._outputFormatter(param);
};
/**
* Should be used to check if a type is variadic
*
* @method isVariadicType
* @param {String} type
* @returns {Bool} true if the type is variadic
*/
SolidityType.prototype.isVariadicType = function (type) {
return isArrayType(type) || this._mode === 'bytes';
};
/**
* Should be used to shift param from params group
*
* @method shiftParam
* @param {String} type
* @returns {SolidityParam} shifted param
*/
SolidityType.prototype.shiftParam = function (type, param) {
if (this._mode === 'bytes') {
return param.shiftBytes();
} else if (isArrayType(type)) {
var length = new BigNumber(param.prefix.slice(0, 64), 16);
return param.shiftArray(length);
}
return param.shiftValue();
};
/**
* SolidityCoder prototype should be used to encode/decode solidity params of any type
*/
var SolidityCoder = function (types) {
this._types = types;
};
/**
* This method should be used to transform type to SolidityType
*
* @method _requireType
* @param {String} type
* @returns {SolidityType}
* @throws {Error} throws if no matching type is found
*/
SolidityCoder.prototype._requireType = function (type) {
var solidityType = this._types.filter(function (t) {
return t.isType(type);
})[0];
if (!solidityType) {
throw Error('invalid solidity type!: ' + type);
}
return solidityType;
};
/**
* Should be used to transform plain bytes to SolidityParam object
*
* @method _bytesToParam
* @param {Array} types of params
* @param {String} bytes to be transformed to SolidityParam
* @return {SolidityParam} SolidityParam for this group of params
*/
SolidityCoder.prototype._bytesToParam = function (types, bytes) {
var self = this;
var prefixTypes = types.reduce(function (acc, type) {
return self._requireType(type).isVariadicType(type) ? acc + 1 : acc;
}, 0);
var valueTypes = types.length - prefixTypes;
var prefix = bytes.slice(0, prefixTypes * 64);
bytes = bytes.slice(prefixTypes * 64);
var value = bytes.slice(0, valueTypes * 64);
var suffix = bytes.slice(valueTypes * 64);
return new SolidityParam(value, prefix, suffix);
};
/**
* Should be used to transform plain param of given type to SolidityParam
*
* @method _formatInput
* @param {String} type of param
* @param {Object} plain param
* @return {SolidityParam}
*/
SolidityCoder.prototype._formatInput = function (type, param) {
return this._requireType(type).formatInput(param, isArrayType(type));
};
/**
* Should be used to encode plain param
*
* @method encodeParam
* @param {String} type
* @param {Object} plain param
* @return {String} encoded plain param
*/
SolidityCoder.prototype.encodeParam = function (type, param) {
return this._formatInput(type, param).encode();
};
/**
* Should be used to encode list of params
*
* @method encodeParams
* @param {Array} types
* @param {Array} params
* @return {String} encoded list of params
*/
SolidityCoder.prototype.encodeParams = function (types, params) {
var self = this;
return types.map(function (type, index) {
return self._formatInput(type, params[index]);
}).reduce(function (acc, solidityParam) {
acc.append(solidityParam);
return acc;
}, new SolidityParam()).encode();
};
/**
* Should be used to transform SolidityParam to plain param
*
* @method _formatOutput
* @param {String} type
* @param {SolidityParam} param
* @return {Object} plain param
*/
SolidityCoder.prototype._formatOutput = function (type, param) {
return this._requireType(type).formatOutput(param, isArrayType(type));
};
/**
* Should be used to decode bytes to plain param
*
* @method decodeParam
* @param {String} type
* @param {String} bytes
* @return {Object} plain param
*/
SolidityCoder.prototype.decodeParam = function (type, bytes) {
return this._formatOutput(type, this._bytesToParam([type], bytes));
};
/**
* Should be used to decode list of params
*
* @method decodeParam
* @param {Array} types
* @param {String} bytes
* @return {Array} array of plain params
*/
SolidityCoder.prototype.decodeParams = function (types, bytes) {
var self = this;
var param = this._bytesToParam(types, bytes);
return types.map(function (type) {
var solidityType = self._requireType(type);
var p = solidityType.shiftParam(type, param);
return solidityType.formatOutput(p, isArrayType(type));
});
};
var coder = new SolidityCoder([
new SolidityType({
name: 'address',
match: 'strict',
mode: 'value',
inputFormatter: f.formatInputInt,
outputFormatter: f.formatOutputAddress
}),
new SolidityType({
name: 'bool',
match: 'strict',
mode: 'value',
inputFormatter: f.formatInputBool,
outputFormatter: f.formatOutputBool
}),
new SolidityType({
name: 'int',
match: 'prefix',
mode: 'value',
inputFormatter: f.formatInputInt,
outputFormatter: f.formatOutputInt,
}),
new SolidityType({
name: 'uint',
match: 'prefix',
mode: 'value',
inputFormatter: f.formatInputInt,
outputFormatter: f.formatOutputUInt
}),
new SolidityType({
name: 'bytes',
match: 'strict',
mode: 'bytes',
inputFormatter: f.formatInputDynamicBytes,
outputFormatter: f.formatOutputDynamicBytes
}),
new SolidityType({
name: 'bytes',
match: 'prefix',
mode: 'value',
inputFormatter: f.formatInputBytes,
outputFormatter: f.formatOutputBytes
}),
new SolidityType({
name: 'real',
match: 'prefix',
mode: 'value',
inputFormatter: f.formatInputReal,
outputFormatter: f.formatOutputReal
}),
new SolidityType({
name: 'ureal',
match: 'prefix',
mode: 'value',
inputFormatter: f.formatInputReal,
outputFormatter: f.formatOutputUReal
})
]);
module.exports = coder;

114
libjsqrc/ethereumjs/lib/solidity/formatters.js

@ -14,15 +14,17 @@
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 formatters.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
/**
* @file formatters.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var BigNumber = require('bignumber.js');
var utils = require('../utils/utils');
var c = require('../utils/config');
var SolidityParam = require('./param');
/**
* Formats input value to byte representation of int
@ -31,23 +33,37 @@ var c = require('../utils/config');
*
* @method formatInputInt
* @param {String|Number|BigNumber} value that needs to be formatted
* @returns {String} right-aligned byte representation of int
* @returns {SolidityParam}
*/
var formatInputInt = function (value) {
var padding = c.ETH_PADDING * 2;
BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);
return utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);
var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);
return new SolidityParam(result);
};
/**
* Formats input value to byte representation of string
*
* @method formatInputString
* @method formatInputBytes
* @param {String}
* @returns {String} left-algined byte representation of string
* @returns {SolidityParam}
*/
var formatInputString = function (value) {
return utils.fromAscii(value, c.ETH_PADDING).substr(2);
var formatInputBytes = function (value) {
var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);
return new SolidityParam(result);
};
/**
* Formats input value to byte representation of string
*
* @method formatInputDynamicBytes
* @param {String}
* @returns {SolidityParam}
*/
var formatInputDynamicBytes = function (value) {
var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);
return new SolidityParam('', formatInputInt(value.length).value, result);
};
/**
@ -55,10 +71,11 @@ var formatInputString = function (value) {
*
* @method formatInputBool
* @param {Boolean}
* @returns {String} right-aligned byte representation bool
* @returns {SolidityParam}
*/
var formatInputBool = function (value) {
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
return new SolidityParam(result);
};
/**
@ -67,10 +84,10 @@ var formatInputBool = function (value) {
*
* @method formatInputReal
* @param {String|Number|BigNumber}
* @returns {String} byte representation of real
* @returns {SolidityParam}
*/
var formatInputReal = function (value) {
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
};
/**
@ -88,12 +105,11 @@ var signedIsNegative = function (value) {
* Formats right-aligned output bytes to int
*
* @method formatOutputInt
* @param {String} bytes
* @param {SolidityParam} param
* @returns {BigNumber} right-aligned output bytes formatted to big number
*/
var formatOutputInt = function (value) {
value = value || "0";
var formatOutputInt = function (param) {
var value = param.value || "0";
// check if it's negative number
// it it is, return two's complement
@ -107,11 +123,11 @@ var formatOutputInt = function (value) {
* Formats right-aligned output bytes to uint
*
* @method formatOutputUInt
* @param {String} bytes
* @param {SolidityParam}
* @returns {BigNumeber} right-aligned output bytes formatted to uint
*/
var formatOutputUInt = function (value) {
value = value || "0";
var formatOutputUInt = function (param) {
var value = param.value || "0";
return new BigNumber(value, 16);
};
@ -119,80 +135,84 @@ var formatOutputUInt = function (value) {
* Formats right-aligned output bytes to real
*
* @method formatOutputReal
* @param {String}
* @param {SolidityParam}
* @returns {BigNumber} input bytes formatted to real
*/
var formatOutputReal = function (value) {
return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128));
var formatOutputReal = function (param) {
return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128));
};
/**
* Formats right-aligned output bytes to ureal
*
* @method formatOutputUReal
* @param {String}
* @param {SolidityParam}
* @returns {BigNumber} input bytes formatted to ureal
*/
var formatOutputUReal = function (value) {
return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128));
var formatOutputUReal = function (param) {
return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128));
};
/**
* Should be used to format output hash
* Should be used to format output bool
*
* @method formatOutputHash
* @param {String}
* @returns {String} right-aligned output bytes formatted to hex
* @method formatOutputBool
* @param {SolidityParam}
* @returns {Boolean} right-aligned input bytes formatted to bool
*/
var formatOutputHash = function (value) {
return "0x" + value;
var formatOutputBool = function (param) {
return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
};
/**
* Should be used to format output bool
* Should be used to format output string
*
* @method formatOutputBool
* @param {String}
* @returns {Boolean} right-aligned input bytes formatted to bool
* @method formatOutputBytes
* @param {SolidityParam} left-aligned hex representation of string
* @returns {String} ascii string
*/
var formatOutputBool = function (value) {
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
var formatOutputBytes = function (param) {
// length might also be important!
return utils.toAscii(param.value);
};
/**
* Should be used to format output string
*
* @method formatOutputString
* @param {Sttring} left-aligned hex representation of string
* @method formatOutputDynamicBytes
* @param {SolidityParam} left-aligned hex representation of string
* @returns {String} ascii string
*/
var formatOutputString = function (value) {
return utils.toAscii(value);
var formatOutputDynamicBytes = function (param) {
// length might also be important!
return utils.toAscii(param.suffix);
};
/**
* Should be used to format output address
*
* @method formatOutputAddress
* @param {String} right-aligned input bytes
* @param {SolidityParam} right-aligned input bytes
* @returns {String} address
*/
var formatOutputAddress = function (value) {
var formatOutputAddress = function (param) {
var value = param.value;
return "0x" + value.slice(value.length - 40, value.length);
};
module.exports = {
formatInputInt: formatInputInt,
formatInputString: formatInputString,
formatInputBytes: formatInputBytes,
formatInputDynamicBytes: formatInputDynamicBytes,
formatInputBool: formatInputBool,
formatInputReal: formatInputReal,
formatOutputInt: formatOutputInt,
formatOutputUInt: formatOutputUInt,
formatOutputReal: formatOutputReal,
formatOutputUReal: formatOutputUReal,
formatOutputHash: formatOutputHash,
formatOutputBool: formatOutputBool,
formatOutputString: formatOutputString,
formatOutputBytes: formatOutputBytes,
formatOutputDynamicBytes: formatOutputDynamicBytes,
formatOutputAddress: formatOutputAddress
};

105
libjsqrc/ethereumjs/lib/solidity/param.js

@ -0,0 +1,105 @@
/*
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 param.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
/**
* SolidityParam object prototype.
* Should be used when encoding, decoding solidity bytes
*/
var SolidityParam = function (value, prefix, suffix) {
this.prefix = prefix || '';
this.value = value || '';
this.suffix = suffix || '';
};
/**
* This method should be used to encode two params one after another
*
* @method append
* @param {SolidityParam} param that it appended after this
*/
SolidityParam.prototype.append = function (param) {
this.prefix += param.prefix;
this.value += param.value;
this.suffix += param.suffix;
};
/**
* This method should be used to encode next param in an array
*
* @method appendArrayElement
* @param {SolidityParam} param that is appended to an array
*/
SolidityParam.prototype.appendArrayElement = function (param) {
this.suffix += param.value;
this.prefix += param.prefix;
// TODO: suffix not supported = it's required for nested arrays;
};
/**
* This method should be used to create bytearrays from param
*
* @method encode
* @return {String} encoded param(s)
*/
SolidityParam.prototype.encode = function () {
return this.prefix + this.value + this.suffix;
};
/**
* This method should be used to shift first param from group of params
*
* @method shiftValue
* @return {SolidityParam} first value param
*/
SolidityParam.prototype.shiftValue = function () {
var value = this.value.slice(0, 64);
this.value = this.value.slice(64);
return new SolidityParam(value);
};
/**
* This method should be used to first bytes param from group of params
*
* @method shiftBytes
* @return {SolidityParam} first bytes param
*/
SolidityParam.prototype.shiftBytes = function () {
return this.shiftArray(1);
};
/**
* This method should be used to shift an array from group of params
*
* @method shiftArray
* @param {Number} size of an array to shift
* @return {SolidityParam} first array param
*/
SolidityParam.prototype.shiftArray = function (length) {
var prefix = this.prefix.slice(0, 64);
this.prefix = this.value.slice(64);
var suffix = this.suffix.slice(0, 64 * length);
this.suffix = this.suffix.slice(64 * length);
return new SolidityParam('', prefix, suffix);
};
module.exports = SolidityParam;

77
libjsqrc/ethereumjs/lib/solidity/types.js

@ -1,77 +0,0 @@
/*
This file is part of ethereum.js.
ethereum.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ethereum.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file types.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var f = require('./formatters');
/// @param expected type prefix (string)
/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false
var prefixedType = function (prefix) {
return function (type) {
return type.indexOf(prefix) === 0;
};
};
/// @param expected type name (string)
/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false
var namedType = function (name) {
return function (type) {
return name === type;
};
};
/// Setups input formatters for solidity types
/// @returns an array of input formatters
var inputTypes = function () {
return [
{ type: prefixedType('uint'), format: f.formatInputInt },
{ type: prefixedType('int'), format: f.formatInputInt },
{ type: prefixedType('bytes'), format: f.formatInputString },
{ type: prefixedType('real'), format: f.formatInputReal },
{ type: prefixedType('ureal'), format: f.formatInputReal },
{ type: namedType('address'), format: f.formatInputInt },
{ type: namedType('bool'), format: f.formatInputBool }
];
};
/// Setups output formaters for solidity types
/// @returns an array of output formatters
var outputTypes = function () {
return [
{ type: prefixedType('uint'), format: f.formatOutputUInt },
{ type: prefixedType('int'), format: f.formatOutputInt },
{ type: prefixedType('bytes'), format: f.formatOutputString },
{ type: prefixedType('real'), format: f.formatOutputReal },
{ type: prefixedType('ureal'), format: f.formatOutputUReal },
{ type: namedType('address'), format: f.formatOutputAddress },
{ type: namedType('bool'), format: f.formatOutputBool }
];
};
module.exports = {
prefixedType: prefixedType,
namedType: namedType,
inputTypes: inputTypes,
outputTypes: outputTypes
};

30
libjsqrc/ethereumjs/lib/solidity/utils.js

@ -34,35 +34,7 @@ var getConstructor = function (abi, numberOfArgs) {
})[0];
};
/**
* Filters all functions from input abi
*
* @method filterFunctions
* @param {Array} abi
* @returns {Array} abi array with filtered objects of type 'function'
*/
var filterFunctions = function (json) {
return json.filter(function (current) {
return current.type === 'function';
});
};
/**
* Filters all events from input abi
*
* @method filterEvents
* @param {Array} abi
* @returns {Array} abi array with filtered objects of type 'event'
*/
var filterEvents = function (json) {
return json.filter(function (current) {
return current.type === 'event';
});
};
module.exports = {
getConstructor: getConstructor,
filterFunctions: filterFunctions,
filterEvents: filterEvents
getConstructor: getConstructor
};

3
libjsqrc/ethereumjs/lib/utils/config.js

@ -64,6 +64,7 @@ module.exports = {
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000,
ETH_DEFAULTBLOCK: 'latest'
defaultBlock: 'latest',
defaultAccount: undefined
};

42
libjsqrc/ethereumjs/lib/utils/utils.js

@ -14,9 +14,9 @@
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 utils.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
/**
* @file utils.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
@ -67,22 +67,6 @@ var padLeft = function (string, chars, sign) {
return new Array(chars - string.length + 1).join(sign ? sign : "0") + string;
};
/** Finds first index of array element matching pattern
*
* @method findIndex
* @param {Array}
* @param {Function} pattern
* @returns {Number} index of element
*/
var findIndex = function (array, callback) {
var end = false;
var i = 0;
for (; i < array.length && !end; i++) {
end = callback(array[i]);
}
return end ? i - 1 : -1;
};
/**
* Should be called to get sting from it's hex representation
*
@ -112,7 +96,7 @@ var toAscii = function(hex) {
/**
* Shold be called to get hex representation (prefixed by 0x) of ascii string
*
* @method fromAscii
* @method toHexNative
* @param {String} string
* @returns {String} hex representation of input string
*/
@ -142,6 +126,22 @@ var fromAscii = function(str, pad) {
return "0x" + hex;
};
/**
* Should be used to create full function/event name from json abi
*
* @method transformToFullName
* @param {Object} json-abi
* @return {String} full fnction/event name
*/
var transformToFullName = function (json) {
if (json.name.indexOf('(') !== -1) {
return json.name;
}
var typeName = json.inputs.map(function(i){return i.type; }).join();
return json.name + '(' + typeName + ')';
};
/**
* Should be called to get display name of contract function
*
@ -448,12 +448,12 @@ var isJson = function (str) {
module.exports = {
padLeft: padLeft,
findIndex: findIndex,
toHex: toHex,
toDecimal: toDecimal,
fromDecimal: fromDecimal,
toAscii: toAscii,
fromAscii: fromAscii,
transformToFullName: transformToFullName,
extractDisplayName: extractDisplayName,
extractTypeName: extractTypeName,
toWei: toWei,

2
libjsqrc/ethereumjs/lib/version.json

@ -1,3 +1,3 @@
{
"version": "0.2.6"
"version": "0.3.3"
}

17
libjsqrc/ethereumjs/lib/web3.js

@ -117,6 +117,8 @@ web3.setProvider = function (provider) {
};
web3.reset = function () {
RequestManager.getInstance().reset();
c.defaultBlock = 'latest';
c.defaultAccount = undefined;
};
web3.toHex = utils.toHex;
web3.toAscii = utils.toAscii;
@ -131,14 +133,23 @@ web3.isAddress = utils.isAddress;
// ADD defaultblock
Object.defineProperty(web3.eth, 'defaultBlock', {
get: function () {
return c.ETH_DEFAULTBLOCK;
return c.defaultBlock;
},
set: function (val) {
c.ETH_DEFAULTBLOCK = val;
return c.ETH_DEFAULTBLOCK;
c.defaultBlock = val;
return val;
}
});
Object.defineProperty(web3.eth, 'defaultAccount', {
get: function () {
return c.defaultAccount;
},
set: function (val) {
c.defaultAccount = val;
return val;
}
});
/// setups all api methods
setupMethods(web3, web3Methods);

184
libjsqrc/ethereumjs/lib/web3/contract.js

@ -14,138 +14,38 @@
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 contract.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
/**
* @file contract.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
var web3 = require('../web3');
var solAbi = require('../solidity/abi');
var utils = require('../utils/utils');
var solUtils = require('../solidity/utils');
var eventImpl = require('./event');
var signature = require('./signature');
var addFunctionRelatedPropertiesToContract = function (contract) {
contract.call = function (options) {
contract._isTransaction = false;
contract._options = options;
return contract;
};
contract.sendTransaction = function (options) {
contract._isTransaction = true;
contract._options = options;
return contract;
};
};
var addFunctionsToContract = function (contract, desc, address) {
var inputParser = solAbi.inputParser(desc);
var outputParser = solAbi.outputParser(desc);
// create contract functions
solUtils.filterFunctions(desc).forEach(function (method) {
var displayName = utils.extractDisplayName(method.name);
var typeName = utils.extractTypeName(method.name);
var impl = function () {
/*jshint maxcomplexity:7 */
var params = Array.prototype.slice.call(arguments);
var sign = signature.functionSignatureFromAscii(method.name);
var parsed = inputParser[displayName][typeName].apply(null, params);
var options = contract._options || {};
options.to = address;
options.data = sign + parsed;
var isTransaction = contract._isTransaction === true || (contract._isTransaction !== false && !method.constant);
var collapse = options.collapse !== false;
// reset
contract._options = {};
contract._isTransaction = null;
if (isTransaction) {
// transactions do not have any output, cause we do not know, when they will be processed
web3.eth.sendTransaction(options);
return;
}
var output = web3.eth.call(options);
var ret = outputParser[displayName][typeName](output);
if (collapse)
{
if (ret.length === 1)
ret = ret[0];
else if (ret.length === 0)
ret = null;
}
return ret;
};
if (contract[displayName] === undefined) {
contract[displayName] = impl;
}
contract[displayName][typeName] = impl;
var SolidityEvent = require('./event');
var SolidityFunction = require('./function');
var addFunctionsToContract = function (contract, desc) {
desc.filter(function (json) {
return json.type === 'function';
}).map(function (json) {
return new SolidityFunction(json, contract.address);
}).forEach(function (f) {
f.attachToContract(contract);
});
};
var addEventRelatedPropertiesToContract = function (contract, desc, address) {
contract.address = address;
contract._onWatchEventResult = function (data) {
var matchingEvent = event.getMatchingEvent(solUtils.filterEvents(desc));
var parser = eventImpl.outputParser(matchingEvent);
return parser(data);
};
Object.defineProperty(contract, 'topics', {
get: function() {
return solUtils.filterEvents(desc).map(function (e) {
return signature.eventSignatureFromAscii(e.name);
});
}
var addEventsToContract = function (contract, desc) {
desc.filter(function (json) {
return json.type === 'event';
}).map(function (json) {
return new SolidityEvent(json, contract.address);
}).forEach(function (e) {
e.attachToContract(contract);
});
};
var addEventsToContract = function (contract, desc, address) {
// create contract events
solUtils.filterEvents(desc).forEach(function (e) {
var impl = function () {
var params = Array.prototype.slice.call(arguments);
var sign = signature.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, sign, e);
var o = event.apply(null, params);
var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.filter(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event
impl._isEvent = true;
var displayName = utils.extractDisplayName(e.name);
var typeName = utils.extractTypeName(e.name);
if (contract[displayName] === undefined) {
contract[displayName] = impl;
}
contract[displayName][typeName] = impl;
});
};
/**
* This method should be called when we want to call / transact some solidity method from javascript
* it returns an object which has same methods available as solidity contract description
@ -174,39 +74,33 @@ var contract = function (abi) {
return Contract.bind(null, abi);
};
function Contract(abi, options) {
var Contract = function (abi, options) {
// workaround for invalid assumption that method.name is the full anonymous prototype of the method.
// it's not. it's just the name. the rest of the code assumes it's actually the anonymous
// prototype, so we make it so as a workaround.
// TODO: we may not want to modify input params, maybe use copy instead?
abi.forEach(function (method) {
if (method.name.indexOf('(') === -1) {
var displayName = method.name;
var typeName = method.inputs.map(function(i){return i.type; }).join();
method.name = displayName + '(' + typeName + ')';
}
});
var address = '';
this.address = '';
if (utils.isAddress(options)) {
address = options;
} else { // is a source code!
this.address = options;
} else { // is an object!
// TODO, parse the rest of the args
var code = options;
options = options || {};
var args = Array.prototype.slice.call(arguments, 2);
var bytes = solAbi.formatConstructorParams(abi, args);
address = web3.eth.sendTransaction({data: code + bytes});
options.data += bytes;
this.address = web3.eth.sendTransaction(options);
}
var result = {};
addFunctionRelatedPropertiesToContract(result);
addFunctionsToContract(result, abi, address);
addEventRelatedPropertiesToContract(result, abi, address);
addEventsToContract(result, abi, address);
addFunctionsToContract(this, abi);
addEventsToContract(this, abi);
};
Contract.prototype.call = function () {
console.error('contract.call is deprecated');
return this;
};
return result;
}
Contract.prototype.sendTransaction = function () {
console.error('contract.sendTransact is deprecated');
return this;
};
module.exports = contract;

22
libjsqrc/ethereumjs/lib/web3/errors.js

@ -20,18 +20,18 @@
* @date 2015
*/
var utils = require('../utils/utils');
module.exports = {
InvalidNumberOfParams: new Error('Invalid number of input parameters'),
InvalidProvider: new Error('Providor not set or invalid'),
InvalidResponse: function(result){
var message = 'Invalid JSON RPC response';
if(utils.isObject(result) && result.error && result.error.message) {
message = result.error.message;
}
InvalidNumberOfParams: function () {
return new Error('Invalid number of input parameters');
},
InvalidConnection: function (host){
return new Error('CONNECTION ERROR: Couldn\'t connect to node '+ host +', is it running?');
},
InvalidProvider: function () {
return new Error('Providor not set or invalid');
},
InvalidResponse: function (result){
var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response';
return new Error(message);
}
};

13
libjsqrc/ethereumjs/lib/web3/eth.js

@ -102,7 +102,7 @@ var getBlock = new Method({
name: 'getBlock',
call: blockCall,
params: 2,
inputFormatter: [utils.toHex, function (val) { return !!val; }],
inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],
outputFormatter: formatters.outputBlockFormatter
});
@ -110,7 +110,7 @@ var getUncle = new Method({
name: 'getUncle',
call: uncleCall,
params: 2,
inputFormatter: [utils.toHex, utils.toHex],
inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],
outputFormatter: formatters.outputBlockFormatter,
});
@ -148,7 +148,7 @@ var getTransactionFromBlock = new Method({
name: 'getTransactionFromBlock',
call: transactionFromBlockCall,
params: 2,
inputFormatter: [utils.toHex, utils.toHex],
inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],
outputFormatter: formatters.outputTransactionFormatter
});
@ -192,12 +192,6 @@ var compileSerpent = new Method({
params: 1
});
var flush = new Method({
name: 'flush',
call: 'eth_flush',
params: 0
});
var methods = [
getBalance,
getStorageAt,
@ -215,7 +209,6 @@ var methods = [
compileSolidity,
compileLLL,
compileSerpent,
flush
];
/// @returns an array of objects describing web3.eth api properties

246
libjsqrc/ethereumjs/lib/web3/event.js

@ -14,125 +14,181 @@
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 event.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
/**
* @file event.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
var abi = require('../solidity/abi');
var utils = require('../utils/utils');
var signature = require('./signature');
/// 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 coder = require('../solidity/coder');
var web3 = require('../web3');
var formatters = require('./formatters');
/**
* This prototype should be used to create event filters
*/
var SolidityEvent = function (json, address) {
this._params = json.inputs;
this._name = utils.transformToFullName(json);
this._address = address;
this._anonymous = json.anonymous;
};
var inputWithName = function (inputs, name) {
var index = utils.findIndex(inputs, function (input) {
return input.name === name;
/**
* Should be used to get filtered param types
*
* @method types
* @param {Bool} decide if returned typed should be indexed
* @return {Array} array of types
*/
SolidityEvent.prototype.types = function (indexed) {
return this._params.filter(function (i) {
return i.indexed === indexed;
}).map(function (i) {
return i.type;
});
if (index === -1) {
console.error('indexed param with name ' + name + ' not found');
return undefined;
}
return inputs[index];
};
var indexedParamsToTopics = function (event, indexed) {
// sort keys?
return Object.keys(indexed).map(function (key) {
var inputs = [inputWithName(filterInputs(event.inputs, true), key)];
/**
* Should be used to get event display name
*
* @method displayName
* @return {String} event display name
*/
SolidityEvent.prototype.displayName = function () {
return utils.extractDisplayName(this._name);
};
/**
* Should be used to get event type name
*
* @method typeName
* @return {String} event type name
*/
SolidityEvent.prototype.typeName = function () {
return utils.extractTypeName(this._name);
};
/**
* Should be used to get event signature
*
* @method signature
* @return {String} event signature
*/
SolidityEvent.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2);
};
/**
* Should be used to encode indexed params and options to one final object
*
* @method encode
* @param {Object} indexed
* @param {Object} options
* @return {Object} everything combined together and encoded
*/
SolidityEvent.prototype.encode = function (indexed, options) {
indexed = indexed || {};
options = options || {};
var result = {};
['fromBlock', 'toBlock'].filter(function (f) {
return options[f] !== undefined;
}).forEach(function (f) {
result[f] = utils.toHex(options[f]);
});
result.topics = [];
if (!this._anonymous) {
result.address = this._address;
result.topics.push('0x' + this.signature());
}
var value = indexed[key];
if (value instanceof Array) {
var indexedTopics = this._params.filter(function (i) {
return i.indexed === true;
}).map(function (i) {
var value = indexed[i.name];
if (value === undefined || value === null) {
return null;
}
if (utils.isArray(value)) {
return value.map(function (v) {
return abi.formatInput(inputs, [v]);
});
return '0x' + coder.encodeParam(i.type, v);
});
}
return '0x' + abi.formatInput(inputs, [value]);
return '0x' + coder.encodeParam(i.type, value);
});
};
var inputParser = function (address, sign, event) {
// valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.filter'
return function (indexed, options) {
var o = options || {};
o.address = address;
o.topics = [];
o.topics.push(sign);
if (indexed) {
o.topics = o.topics.concat(indexedParamsToTopics(event, indexed));
}
return o;
};
};
result.topics = result.topics.concat(indexedTopics);
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 = indexedCopy.splice(0, 1)[0];
else
value = notIndexedCopy.splice(0, 1)[0];
acc[current.name] = value;
return acc;
}, {});
return result;
};
/**
* Should be used to decode indexed params and options
*
* @method decode
* @param {Object} data
* @return {Object} result object with decoded indexed && not indexed params
*/
SolidityEvent.prototype.decode = function (data) {
var outputParser = function (event) {
data.data = data.data || '';
data.topics = data.topics || [];
var argTopics = this._anonymous ? data.topics : data.topics.slice(1);
var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join("");
var indexedParams = coder.decodeParams(this.types(true), indexedData);
var notIndexedData = data.data.slice(2);
var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);
return function (output) {
var result = {
event: utils.extractDisplayName(event.name),
number: output.number,
hash: output.hash,
args: {}
};
if (!output.topics) {
return result;
}
output.data = output.data || '';
var indexedOutputs = filterInputs(event.inputs, true);
var indexedData = "0x" + output.topics.slice(1, output.topics.length).map(function (topics) { return topics.slice(2); }).join("");
var indexedRes = abi.formatOutput(indexedOutputs, indexedData);
var result = formatters.outputLogFormatter(data);
result.event = this.displayName();
result.address = data.address;
var notIndexedOutputs = filterInputs(event.inputs, false);
var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);
result.args = this._params.reduce(function (acc, current) {
acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();
return acc;
}, {});
result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);
delete result.data;
delete result.topics;
return result;
};
return result;
};
var getMatchingEvent = function (events, payload) {
for (var i = 0; i < events.length; i++) {
var sign = signature.eventSignatureFromAscii(events[i].name);
if (sign === payload.topics[0]) {
return events[i];
}
}
return undefined;
/**
* Should be used to create new filter object from event
*
* @method execute
* @param {Object} indexed
* @param {Object} options
* @return {Object} filter object
*/
SolidityEvent.prototype.execute = function (indexed, options) {
var o = this.encode(indexed, options);
var formatter = this.decode.bind(this);
return web3.eth.filter(o, undefined, undefined, formatter);
};
module.exports = {
inputParser: inputParser,
outputParser: outputParser,
getMatchingEvent: getMatchingEvent
/**
* Should be used to attach event to contract object
*
* @method attachToContract
* @param {Contract}
*/
SolidityEvent.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this);
var displayName = this.displayName();
if (!contract[displayName]) {
contract[displayName] = execute;
}
contract[displayName][this.typeName()] = this.execute.bind(this, contract);
};
module.exports = SolidityEvent;

57
libjsqrc/ethereumjs/lib/web3/filter.js

@ -28,6 +28,25 @@ var RequestManager = require('./requestmanager');
var formatters = require('./formatters');
var utils = require('../utils/utils');
/**
* Converts a given topic to a hex string, but also allows null values.
*
* @param {Mixed} value
* @return {String}
*/
var toTopic = function(value){
if(value === null || typeof value === 'undefined')
return null;
value = String(value);
if(value.indexOf('0x') === 0)
return value;
else
return utils.fromAscii(value);
};
/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones
/// @param should be string or object
/// @returns options string or object
@ -42,7 +61,7 @@ var getOptions = function (options) {
// make sure topics, get converted to hex
options.topics = options.topics || [];
options.topics = options.topics.map(function(topic){
return utils.toHex(topic);
return (utils.isArray(topic)) ? topic.map(toTopic) : toTopic(topic);
});
// lazy load
@ -86,6 +105,20 @@ Filter.prototype.watch = function (callback) {
});
};
// call getFilterLogs on start
if (!utils.isString(this.options)) {
this.get(function (err, messages) {
// don't send all the responses to all the watches again... just to this one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
});
}
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
@ -98,12 +131,24 @@ Filter.prototype.stopWatching = function () {
this.callbacks = [];
};
Filter.prototype.get = function () {
var logs = this.implementation.getLogs(this.filterId);
Filter.prototype.get = function (callback) {
var self = this;
return logs.map(function (log) {
return self.formatter ? self.formatter(log) : log;
});
if (utils.isFunction(callback)) {
this.implementation.getLogs(this.filterId, function(err, res){
if (err) {
callback(err);
} else {
callback(null, res.map(function (log) {
return self.formatter ? self.formatter(log) : log;
}));
}
});
} else {
var logs = this.implementation.getLogs(this.filterId);
return logs.map(function (log) {
return self.formatter ? self.formatter(log) : log;
});
}
};
module.exports = Filter;

15
libjsqrc/ethereumjs/lib/web3/formatters.js

@ -41,7 +41,7 @@ var isPredefinedBlockNumber = function (blockNumber) {
var inputDefaultBlockNumberFormatter = function (blockNumber) {
if (blockNumber === undefined) {
return config.ETH_DEFAULTBLOCK;
return config.defaultBlock;
}
return inputBlockNumberFormatter(blockNumber);
};
@ -64,6 +64,8 @@ var inputBlockNumberFormatter = function (blockNumber) {
*/
var inputTransactionFormatter = function (options){
options.from = options.from || config.defaultAccount;
// make code -> data
if (options.code) {
options.data = options.code;
@ -89,6 +91,7 @@ var inputTransactionFormatter = function (options){
var outputTransactionFormatter = function (tx){
tx.blockNumber = utils.toDecimal(tx.blockNumber);
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.nonce = utils.toDecimal(tx.nonce);
tx.gas = utils.toDecimal(tx.gas);
tx.gasPrice = utils.toBigNumber(tx.gasPrice);
tx.value = utils.toBigNumber(tx.value);
@ -111,7 +114,6 @@ var outputBlockFormatter = function(block) {
block.timestamp = utils.toDecimal(block.timestamp);
block.number = utils.toDecimal(block.number);
block.minGasPrice = utils.toBigNumber(block.minGasPrice);
block.difficulty = utils.toBigNumber(block.difficulty);
block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);
@ -155,10 +157,12 @@ var inputPostFormatter = function(post) {
post.payload = utils.toHex(post.payload);
post.ttl = utils.fromDecimal(post.ttl);
post.workToProve = utils.fromDecimal(post.workToProve);
post.priority = utils.fromDecimal(post.priority);
if(!utils.isArray(post.topics)) {
post.topics = [post.topics];
// fallback
if (!utils.isArray(post.topics)) {
post.topics = post.topics ? [post.topics] : [];
}
// format the following options
@ -190,6 +194,9 @@ var outputPostFormatter = function(post){
}
// format the following options
if (!post.topics) {
post.topics = [];
}
post.topics = post.topics.map(function(topic){
return utils.toAscii(topic);
});

151
libjsqrc/ethereumjs/lib/web3/function.js

@ -0,0 +1,151 @@
/*
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 function.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
*/
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
/**
* This prototype should be used to call/sendTransaction to solidity functions
*/
var SolidityFunction = function (json, address) {
this._inputTypes = json.inputs.map(function (i) {
return i.type;
});
this._outputTypes = json.outputs.map(function (i) {
return i.type;
});
this._constant = json.constant;
this._name = utils.transformToFullName(json);
this._address = address;
};
/**
* Should be used to create payload from arguments
*
* @method toPayload
* @param {...} solidity function params
* @param {Object} optional payload options
*/
SolidityFunction.prototype.toPayload = function () {
var args = Array.prototype.slice.call(arguments);
var options = {};
if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {
options = args.pop();
}
options.to = this._address;
options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);
return options;
};
/**
* Should be used to get function signature
*
* @method signature
* @return {String} function signature
*/
SolidityFunction.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);
};
/**
* Should be used to call function
*
* @method call
* @param {Object} options
* @return {String} output bytes
*/
SolidityFunction.prototype.call = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));
var output = web3.eth.call(payload);
output = output.length >= 2 ? output.slice(2) : output;
var result = coder.decodeParams(this._outputTypes, output);
return result.length === 1 ? result[0] : result;
};
/**
* Should be used to sendTransaction to solidity function
*
* @method sendTransaction
* @param {Object} options
*/
SolidityFunction.prototype.sendTransaction = function () {
var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));
web3.eth.sendTransaction(payload);
};
/**
* Should be used to get function display name
*
* @method displayName
* @return {String} display name of the function
*/
SolidityFunction.prototype.displayName = function () {
return utils.extractDisplayName(this._name);
};
/**
* Should be used to get function type name
*
* @method typeName
* @return {String} type name of the function
*/
SolidityFunction.prototype.typeName = function () {
return utils.extractTypeName(this._name);
};
/**
* Should be called to execute function
*
* @method execute
*/
SolidityFunction.prototype.execute = function () {
var transaction = !this._constant;
// send transaction
if (transaction) {
return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));
}
// call
return this.call.apply(this, Array.prototype.slice.call(arguments));
};
/**
* Should be called to attach function to contract
*
* @method attachToContract
* @param {Contract}
*/
SolidityFunction.prototype.attachToContract = function (contract) {
var execute = this.execute.bind(this);
execute.call = this.call.bind(this);
execute.sendTransaction = this.sendTransaction.bind(this);
var displayName = this.displayName();
if (!contract[displayName]) {
contract[displayName] = execute;
}
contract[displayName][this.typeName()] = execute; // circular!!!!
};
module.exports = SolidityFunction;

18
libjsqrc/ethereumjs/lib/web3/httpprovider.js

@ -25,16 +25,23 @@
"use strict";
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
var errors = require('./errors');
var HttpProvider = function (host) {
this.host = host || 'http://localhost:8080';
this.host = host || 'http://localhost:8545';
};
HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
try {
request.send(JSON.stringify(payload));
} catch(error) {
throw errors.InvalidConnection(this.host);
}
// check request.status
// TODO: throw an error here! it cannot silently fail!!!
@ -54,7 +61,12 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
};
request.open('POST', this.host, true);
request.send(JSON.stringify(payload));
try {
request.send(JSON.stringify(payload));
} catch(error) {
callback(errors.InvalidConnection(this.host));
}
};
module.exports = HttpProvider;

2
libjsqrc/ethereumjs/lib/web3/method.js

@ -66,7 +66,7 @@ Method.prototype.extractCallback = function (args) {
*/
Method.prototype.validateArgs = function (args) {
if (args.length !== this.params) {
throw errors.InvalidNumberOfParams;
throw errors.InvalidNumberOfParams();
}
};

6
libjsqrc/ethereumjs/lib/web3/requestmanager.js

@ -65,7 +65,7 @@ RequestManager.getInstance = function () {
*/
RequestManager.prototype.send = function (data) {
if (!this.provider) {
console.error(errors.InvalidProvider);
console.error(errors.InvalidProvider());
return null;
}
@ -88,7 +88,7 @@ RequestManager.prototype.send = function (data) {
*/
RequestManager.prototype.sendAsync = function (data, callback) {
if (!this.provider) {
return callback(errors.InvalidProvider);
return callback(errors.InvalidProvider());
}
var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);
@ -179,7 +179,7 @@ RequestManager.prototype.poll = function () {
}
if (!this.provider) {
console.error(errors.InvalidProvider);
console.error(errors.InvalidProvider());
return;
}

2
libjsqrc/ethereumjs/lib/web3/shh.js

@ -27,7 +27,7 @@ var post = new Method({
name: 'post',
call: 'shh_post',
params: 1,
inputFormatter: formatters.inputPostFormatter
inputFormatter: [formatters.inputPostFormatter]
});
var newIdentity = new Method({

42
libjsqrc/ethereumjs/lib/web3/signature.js

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

2
libjsqrc/ethereumjs/package-init.js

@ -1,7 +1,7 @@
/* jshint ignore:start */
if(typeof web3 === 'undefined') {
web3 = require('ethereum.js');
web3 = require('web3');
BigNumber = require('bignumber.js');
}

7
libjsqrc/ethereumjs/package.js

@ -1,7 +1,7 @@
/* jshint ignore:start */
Package.describe({
name: 'ethereum:js',
version: '0.2.6',
name: 'ethereum:web3',
version: '0.3.3',
summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC',
git: 'https://github.com/ethereum/ethereum.js',
// By default, Meteor will default to using README.md for documentation.
@ -14,10 +14,9 @@ Package.onUse(function(api) {
// api.use('3stack:bignumber@2.0.0', 'client');
// api.export('BigNumber', 'client');
api.export(['web3', 'BigNumber'], 'client');
api.addFiles('dist/ethereum.js', 'client');
api.addFiles('dist/web3.js', 'client');
api.addFiles('package-init.js', 'client');
});

4
libjsqrc/ethereumjs/package.json

@ -1,14 +1,14 @@
{
"name": "web3",
"namespace": "ethereum",
"version": "0.2.6",
"version": "0.3.3",
"description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC",
"main": "./index.js",
"directories": {
"lib": "./lib"
},
"dependencies": {
"bignumber.js": ">=2.0.0",
"bignumber.js": "debris/bignumber.js#master",
"xmlhttprequest": "*"
},
"browser": {

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

@ -469,10 +469,10 @@ describe('lib/solidity/abi', function () {
var parser = abi.inputParser(d);
// then
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000");
assert.equal(parser.test(1), "0000000000000000000000000000000100000000000000000000000000000000");
assert.equal(parser.test(2.125), "0000000000000000000000000000000220000000000000000000000000000000");
assert.equal(parser.test(8.5), "0000000000000000000000000000000880000000000000000000000000000000");
assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000");
});
@ -489,9 +489,9 @@ describe('lib/solidity/abi', function () {
var parser = abi.inputParser(d);
// then
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
assert.equal(parser.test(1), "0000000000000000000000000000000100000000000000000000000000000000");
assert.equal(parser.test(2.125), "0000000000000000000000000000000220000000000000000000000000000000");
assert.equal(parser.test(8.5), "0000000000000000000000000000000880000000000000000000000000000000");
});

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

@ -35,13 +35,13 @@ describe('lib/solidity/abi', function() {
// then
assert.equal(
parser.test("0x" +
parser.test(
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
parser.test(
"0000000000000000000000000000000000000000000000000000000000000005" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'world'
@ -62,14 +62,14 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
@ -87,14 +87,14 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
@ -112,14 +112,14 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("0x000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10),
new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10)
);
assert.equal(
parser.test("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10),
new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10)
);
});
@ -137,10 +137,10 @@ describe('lib/solidity/abi', function() {
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);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int256', function() {
@ -156,10 +156,10 @@ describe('lib/solidity/abi', function() {
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);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output int128', function() {
@ -175,10 +175,10 @@ describe('lib/solidity/abi', function() {
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);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10);
assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1);
assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16);
});
it('should parse output address', function() {
@ -195,7 +195,7 @@ describe('lib/solidity/abi', function() {
// then
assert.equal(
parser.test("0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
parser.test("000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0],
"0x407d73d8a49eeb85d32cf465507dd71d507100c1"
);
});
@ -213,8 +213,8 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000001")[0], true);
assert.equal(parser.test("0x0000000000000000000000000000000000000000000000000000000000000000")[0], false);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], true);
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000000")[0], false);
});
@ -232,10 +232,10 @@ describe('lib/solidity/abi', function() {
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);
assert.equal(parser.test("0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
assert.equal(parser.test("ffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1);
});
@ -252,9 +252,9 @@ describe('lib/solidity/abi', function() {
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("0000000000000000000000000000000100000000000000000000000000000000")[0], 1);
assert.equal(parser.test("0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125);
assert.equal(parser.test("0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5);
});
@ -274,7 +274,7 @@ describe('lib/solidity/abi', function() {
// then
assert.equal(
parser.test("0x" +
parser.test(
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
@ -282,7 +282,7 @@ describe('lib/solidity/abi', function() {
'hello'
);
assert.equal(
parser.test("0x" +
parser.test(
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
@ -305,8 +305,8 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.helloworld("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld['int']("0x0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.helloworld['int']("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
});
@ -330,8 +330,8 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
//then
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test2("0x" +
assert.equal(parser.test("00000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test2(
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
"hello"
@ -351,13 +351,13 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x" +
assert.equal(parser.test(
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][0],
5
);
assert.equal(parser.test("0x" +
assert.equal(parser.test(
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000006")[0][1],
@ -366,7 +366,7 @@ describe('lib/solidity/abi', function() {
});
it('should parse 0x value', function () {
it('should parse 0x0 value', function () {
// given
var d = clone(description);
@ -378,11 +378,11 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
assert.equal(parser.test("0x0")[0], 0);
});
it('should parse 0x value', function () {
it('should parse 0x0 value', function () {
// given
var d = clone(description);
@ -394,7 +394,7 @@ describe('lib/solidity/abi', function() {
var parser = abi.outputParser(d);
// then
assert.equal(parser.test("0x")[0], 0);
assert.equal(parser.test("0x0")[0], 0);
});

68
libjsqrc/ethereumjs/test/coder.decodeParam.js

@ -0,0 +1,68 @@
var chai = require('chai');
var assert = chai.assert;
var coder = require('../lib/solidity/coder');
var BigNumber = require('bignumber.js');
var bn = BigNumber;
describe('lib/solidity/coder', function () {
describe('decodeParam', function () {
var test = function (t) {
it('should turn ' + t.value + ' to ' + t.expected, function () {
assert.deepEqual(coder.decodeParam(t.type, t.value), t.expected);
});
};
test({ type: 'int', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ type: 'int', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ type: 'int', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ type: 'int256', expected: new bn(1), value: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ type: 'int256', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ type: 'int256', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ type: 'bytes32', expected: 'gavofyork', value: '6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000009' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ type: 'int256[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ type: 'int[]', expected: [new bn(1), new bn(2), new bn(3)],
value: '0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000002' +
'0000000000000000000000000000000000000000000000000000000000000003'});
});
});
describe('lib/solidity/coder', function () {
describe('decodeParams', function () {
var test = function (t) {
it('should turn ' + t.values + ' to ' + t.expected, function () {
assert.deepEqual(coder.decodeParams(t.types, t.values), t.expected);
});
};
test({ types: ['int'], expected: [new bn(1)], values: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ types: ['bytes32', 'int'], expected: ['gavofyork', new bn(5)],
values: '6761766f66796f726b0000000000000000000000000000000000000000000000' +
'0000000000000000000000000000000000000000000000000000000000000005'});
test({ types: ['int', 'bytes32'], expected: [new bn(5), 'gavofyork'],
values: '0000000000000000000000000000000000000000000000000000000000000005' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4),
[new bn(5), new bn(6), new bn(7)]],
values: '0000000000000000000000000000000000000000000000000000000000000009' +
'0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000002' +
'0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000004' +
'6761766f66796f726b0000000000000000000000000000000000000000000000' +
'0000000000000000000000000000000000000000000000000000000000000005' +
'0000000000000000000000000000000000000000000000000000000000000006' +
'0000000000000000000000000000000000000000000000000000000000000007'});
});
});

91
libjsqrc/ethereumjs/test/coder.encodeParam.js

@ -0,0 +1,91 @@
var chai = require('chai');
var assert = chai.assert;
var coder = require('../lib/solidity/coder');
describe('lib/solidity/coder', function () {
describe('encodeParam', function () {
var test = function (t) {
it('should turn ' + t.value + ' to ' + t.expected, function () {
assert.equal(coder.encodeParam(t.type, t.value), t.expected);
});
};
test({ type: 'int', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ type: 'int', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ type: 'int', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ type: 'int256', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ type: 'int256', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ type: 'int256', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ type: 'bytes32', value: 'gavofyork', expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000009' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ type: 'int256[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ type: 'int[]', value: [1,2,3], expected: '0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000002' +
'0000000000000000000000000000000000000000000000000000000000000003'});
});
});
describe('lib/solidity/coder', function () {
describe('encodeParams', function () {
var test = function (t) {
it('should turn ' + t.values + ' to ' + t.expected, function () {
assert.equal(coder.encodeParams(t.types, t.values), t.expected);
});
};
test({ types: ['int'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ types: ['int'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ types: ['int'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ types: ['int256'], values: [1], expected: '0000000000000000000000000000000000000000000000000000000000000001'});
test({ types: ['int256'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'});
test({ types: ['int256'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});
test({ types: ['bytes32'], values: ['gavofyork'], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000009' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ types: ['int256[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ types: ['int256[]'], values: [[1,2,3]], expected: '0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000002' +
'0000000000000000000000000000000000000000000000000000000000000003'});
test({ types: ['bytes32', 'int'], values: ['gavofyork', 5],
expected: '6761766f66796f726b0000000000000000000000000000000000000000000000' +
'0000000000000000000000000000000000000000000000000000000000000005'});
test({ types: ['int', 'bytes32'], values: [5, 'gavofyork'],
expected: '0000000000000000000000000000000000000000000000000000000000000005' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['bytes', 'int'], values: ['gavofyork', 5],
expected: '0000000000000000000000000000000000000000000000000000000000000009' +
'0000000000000000000000000000000000000000000000000000000000000005' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['int', 'bytes'], values: [5, 'gavofyork'],
expected: '0000000000000000000000000000000000000000000000000000000000000009' +
'0000000000000000000000000000000000000000000000000000000000000005' +
'6761766f66796f726b0000000000000000000000000000000000000000000000'});
test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]],
expected: '0000000000000000000000000000000000000000000000000000000000000009' +
'0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000002' +
'0000000000000000000000000000000000000000000000000000000000000003' +
'0000000000000000000000000000000000000000000000000000000000000004' +
'6761766f66796f726b0000000000000000000000000000000000000000000000' +
'0000000000000000000000000000000000000000000000000000000000000005' +
'0000000000000000000000000000000000000000000000000000000000000006' +
'0000000000000000000000000000000000000000000000000000000000000007'});
});
});

147
libjsqrc/ethereumjs/test/contract.js

@ -2,7 +2,9 @@ var chai = require('chai');
var assert = chai.assert;
var web3 = require('../index');
var FakeHttpProvider = require('./helpers/FakeHttpProvider');
var FakeHttpProvider2 = require('./helpers/FakeHttpProvider2');
var utils = require('../lib/utils/utils');
var BigNumber = require('bignumber.js');
var desc = [{
"name": "balance(address)",
@ -27,6 +29,18 @@ var desc = [{
"type": "uint256"
}],
"outputs": []
}, {
"name": "testArr(int[])",
"type": "function",
"inputs": [{
"name": "value",
"type": "int[]"
}],
"constant": true,
"outputs": [{
"name": "d",
"type": "int"
}]
}, {
"name":"Changed",
"type":"event",
@ -63,11 +77,27 @@ describe('web3.eth.contract', function () {
assert.deepEqual(payload.params[0], {
topics: [
sha3,
'0x1234567890123456789012345678901234567890'
'0x0000000000000000000000001234567890123456789012345678901234567890',
null
],
address: '0x1234567890123456789012345678901234567890'
});
} else if (step === 2 && utils.isArray(payload)) {
} else if (step === 2) {
step = 3;
provider.injectResult([{
address: address,
topics: [
sha3,
'0x0000000000000000000000001234567890123456789012345678901234567890',
'0x0000000000000000000000000000000000000000000000000000000000000001'
],
number: 2,
data: '0x0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000008'
}]);
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'eth_getFilterLogs');
} else if (step === 3 && utils.isArray(payload)) {
provider.injectBatchResults([[{
address: address,
topics: [
@ -89,12 +119,16 @@ describe('web3.eth.contract', function () {
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
var res = 0;
contract.Changed({from: address}).watch(function(err, result) {
assert.equal(result.args.from, address);
assert.equal(result.args.amount, 1);
assert.equal(result.args.t1, 1);
assert.equal(result.args.t2, 8);
done();
res++;
if (res === 2) {
done();
}
});
});
@ -187,7 +221,40 @@ describe('web3.eth.contract', function () {
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
contract.call({from: address, gas: 50000}).balance(address);
contract.balance(address, {from: address, gas: 50000});
});
it('should explicitly make a call with optional params', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
var sha3 = '0x5131231231231231231231';
var address = '0x1234567890123456789012345678901234567890';
provider.injectResult(sha3);
var step = 0;
provider.injectValidation(function (payload) {
if (step === 0) {
step = 1;
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'web3_sha3');
assert.equal(payload.params[0], web3.fromAscii('balance(address)'));
} else if (step === 1) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: sha3.slice(0, 10) + '0000000000000000000000001234567890123456789012345678901234567890',
to: address,
from: address,
gas: '0xc350'
}, 'latest']);
}
});
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
contract.balance.call(address, {from: address, gas: 50000});
});
@ -223,7 +290,77 @@ describe('web3.eth.contract', function () {
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
contract.sendTransaction({from: address, gas: 50000, gasPrice: 3000, value: 10000}).send(address, 17);
contract.send(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000});
});
it('should explicitly sendTransaction with optional params', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
var sha3 = '0x5131231231231231231231';
var address = '0x1234567890123456789012345678901234567890';
provider.injectResult(sha3);
var step = 0;
provider.injectValidation(function (payload) {
if (step === 0) {
step = 1;
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'web3_sha3');
assert.equal(payload.params[0], web3.fromAscii('send(address,uint256)'));
} else if (step === 1) {
assert.equal(payload.method, 'eth_sendTransaction');
assert.deepEqual(payload.params, [{
data: sha3.slice(0, 10) +
'0000000000000000000000001234567890123456789012345678901234567890' +
'0000000000000000000000000000000000000000000000000000000000000011' ,
to: address,
from: address,
gas: '0xc350',
gasPrice: '0xbb8',
value: '0x2710'
}]);
}
});
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000});
});
it('should call testArr method and properly parse result', function () {
var provider = new FakeHttpProvider2();
web3.setProvider(provider);
web3.reset();
var sha3 = '0x5131231231231231231231';
var address = '0x1234567890123456789012345678901234567890';
provider.injectResultList([{
result: sha3
}, {
result: '0x0000000000000000000000000000000000000000000000000000000000000005'
}]);
var step = 0;
provider.injectValidation(function (payload) {
if (step === 1) { // getting sha3 is first
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: sha3.slice(0, 10) +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000003',
to: address
},
'latest'
]);
}
step++;
});
var Contract = web3.eth.contract(desc);
var contract = new Contract(address);
var result = contract.testArr([3]);
assert.deepEqual(new BigNumber(5), result);
});
});
});

180
libjsqrc/ethereumjs/test/event.decode.js

@ -0,0 +1,180 @@
var chai = require('chai');
var assert = chai.assert;
var BigNumber = require('bignumber.js');
var SolidityEvent = require('../lib/web3/event');
var name = 'event1';
var address = '0x1234567890123456789012345678901234567890';
var tests = [{
abi: {
name: name,
inputs: []
},
data: {
logIndex: '0x1',
transactionIndex: '0x10',
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: '0x1'
},
expected: {
event: name,
args: {},
logIndex: 1,
transactionIndex: 16,
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: 1
}
}, {
abi: {
name: name,
inputs: [{
name: 'a',
type: 'int',
indexed: false
}]
},
data: {
logIndex: '0x1',
transactionIndex: '0x10',
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: '0x1',
data: '0x0000000000000000000000000000000000000000000000000000000000000001'
},
expected: {
event: name,
args: {
a: new BigNumber(1)
},
logIndex: 1,
transactionIndex: 16,
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: 1
}
}, {
abi: {
name: name,
inputs: [{
name: 'a',
type: 'int',
indexed: false
}, {
name: 'b',
type: 'int',
indexed: true
}, {
name: 'c',
type: 'int',
indexed: false
}, {
name: 'd',
type: 'int',
indexed: true
}]
},
data: {
logIndex: '0x1',
transactionIndex: '0x10',
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: '0x1',
data: '0x' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000004',
topics: [
address,
'0x000000000000000000000000000000000000000000000000000000000000000a',
'0x0000000000000000000000000000000000000000000000000000000000000010'
]
},
expected: {
event: name,
args: {
a: new BigNumber(1),
b: new BigNumber(10),
c: new BigNumber(4),
d: new BigNumber(16)
},
logIndex: 1,
transactionIndex: 16,
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: 1
}
}, {
abi: {
name: name,
anonymous: true,
inputs: [{
name: 'a',
type: 'int',
indexed: false
}, {
name: 'b',
type: 'int',
indexed: true
}, {
name: 'c',
type: 'int',
indexed: false
}, {
name: 'd',
type: 'int',
indexed: true
}]
},
data: {
logIndex: '0x1',
transactionIndex: '0x10',
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: '0x1',
data: '0x' +
'0000000000000000000000000000000000000000000000000000000000000001' +
'0000000000000000000000000000000000000000000000000000000000000004',
topics: [
'0x000000000000000000000000000000000000000000000000000000000000000a',
'0x0000000000000000000000000000000000000000000000000000000000000010'
]
},
expected: {
event: name,
args: {
a: new BigNumber(1),
b: new BigNumber(10),
c: new BigNumber(4),
d: new BigNumber(16)
},
logIndex: 1,
transactionIndex: 16,
transactionHash: '0x1234567890',
address: address,
blockHash: '0x1234567890',
blockNumber: 1
}
}];
describe('lib/web3/event', function () {
describe('decode', function () {
tests.forEach(function (test, index) {
it('test no: ' + index, function () {
var event = new SolidityEvent(test.abi, address);
var result = event.decode(test.data);
assert.deepEqual(result, test.expected);
});
});
});
});

206
libjsqrc/ethereumjs/test/event.encode.js

@ -0,0 +1,206 @@
var chai = require('chai');
var assert = chai.assert;
var SolidityEvent = require('../lib/web3/event');
var address = '0x1234567890123456789012345678901234567890';
var signature = '0xffff';
var tests = [{
abi: {
name: 'event1',
inputs: []
},
indexed: {},
options: {},
expected: {
address: address,
topics: [
signature
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}]
},
indexed: {
a: 16
},
options: {},
expected: {
address: address,
topics: [
signature,
'0x0000000000000000000000000000000000000000000000000000000000000010'
]
}
},{
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}, {
type: 'int',
name: 'b',
indexed: true
}, {
type: 'int',
name: 'c',
indexed: false
}, {
type: 'int',
name: 'd',
indexed: true
}]
},
indexed: {
b: 4
},
options: {},
expected: {
address: address,
topics: [
signature, // signature
null, // a
'0x0000000000000000000000000000000000000000000000000000000000000004', // b
null // d
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}, {
type: 'int',
name: 'b',
indexed: true
}]
},
indexed: {
a: [16, 1],
b: 2
},
options: {},
expected: {
address: address,
topics: [
signature,
['0x0000000000000000000000000000000000000000000000000000000000000010', '0x0000000000000000000000000000000000000000000000000000000000000001'],
'0x0000000000000000000000000000000000000000000000000000000000000002'
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}]
},
indexed: {
a: null
},
options: {},
expected: {
address: address,
topics: [
signature,
null
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}]
},
indexed: {
a: 1
},
options: {
fromBlock: 4,
toBlock: 10
},
expected: {
address: address,
fromBlock: '0x4',
toBlock: '0xa',
topics: [
signature,
'0x0000000000000000000000000000000000000000000000000000000000000001'
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}],
anonymous: true
},
indexed: {
a: 1
},
options: {},
expected: {
topics: [
'0x0000000000000000000000000000000000000000000000000000000000000001'
]
}
}, {
abi: {
name: 'event1',
inputs: [{
type: 'int',
name: 'a',
indexed: true
}, {
type: 'int',
name: 'b',
indexed: true
}],
anonymous: true
},
indexed: {
b: 1
},
options: {},
expected: {
topics: [
null,
'0x0000000000000000000000000000000000000000000000000000000000000001'
]
}
}];
describe('lib/web3/event', function () {
describe('encode', function () {
tests.forEach(function (test, index) {
it('test no: ' + index, function () {
var event = new SolidityEvent(test.abi, address);
event.signature = function () { // inject signature
return signature.slice(2);
};
var result = event.encode(test.indexed, test.options);
assert.deepEqual(result, test.expected);
});
});
});
});

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

@ -1,113 +0,0 @@
var assert = require('assert');
var event = require('../lib/web3/event.js');
var f = require('../lib/solidity/formatters.js');
describe('lib/web3/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.topics.length, 1);
assert.equal(result.topics[0], signature);
});
it('should create filter input object with options', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
fromBlock: 1,
toBlock: 2,
};
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.topics.length, 1);
assert.equal(result.topics[0], signature);
assert.equal(result.fromBlock, options.fromBlock);
assert.equal(result.toBlock, options.toBlock);
});
it('should create filter input object with indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
fromBlock: 1,
toBlock: 2
};
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.topics.length, 2);
assert.equal(result.topics[0], signature);
assert.equal(result.topics[1], '0x' + f.formatInputInt(4));
assert.equal(result.fromBlock, options.fromBlock);
assert.equal(result.toBlock, options.toBlock);
});
it('should create filter input object with an array of indexed params', function () {
// given
var address = '0x012345';
var signature = '0x987654';
var options = {
fromBlock: 1,
toBlock: 2,
};
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.topics.length, 2);
assert.equal(result.topics[0], signature);
assert.equal(result.topics[1][0], f.formatInputInt(4));
assert.equal(result.topics[1][1], f.formatInputInt(69));
assert.equal(result.fromBlock, options.fromBlock);
assert.equal(result.toBlock, options.toBlock);
});
});
});

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

Loading…
Cancel
Save