Browse Source

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

mix_project_tree

Conflicts:
	libweb3jsonrpc/WebThreeStubServer.cpp
	libweb3jsonrpc/WebThreeStubServer.h
cl-refactor
arkpar 10 years ago
parent
commit
f6121e0998
  1. 1
      CMakeLists.txt
  2. 12
      alethzero/Main.ui
  3. 38
      alethzero/MainWin.cpp
  4. 9
      alethzero/MainWin.h
  5. 6
      eth/main.cpp
  6. 3
      libdevcrypto/Common.cpp
  7. 17
      libdevcrypto/CryptoPP.cpp
  8. 127
      libethereum/Client.cpp
  9. 33
      libethereum/Client.h
  10. 2
      libethereum/EthereumPeer.cpp
  11. 15
      libethereum/Interface.h
  12. 17
      libethereum/LogFilter.cpp
  13. 6
      libethereum/State.cpp
  14. 4
      libethereum/State.h
  15. 17
      libethereum/Utility.cpp
  16. 10
      libevm/ExtVMFace.h
  17. 760
      libevm/VM.cpp
  18. 761
      libevm/VM.h
  19. 4
      libjsqrc/ethereumjs/.travis.yml
  20. 26
      libjsqrc/ethereumjs/README.md
  21. 19
      libjsqrc/ethereumjs/dist/ethereum.js
  22. 6
      libjsqrc/ethereumjs/dist/ethereum.js.map
  23. 2
      libjsqrc/ethereumjs/dist/ethereum.min.js
  24. 13
      libjsqrc/ethereumjs/lib/abi.js
  25. 6
      libjsqrc/ethereumjs/lib/contract.js
  26. 6
      libjsqrc/ethereumjs/package.json
  27. 37
      libjsqrc/ethereumjs/test/abi.parsers.js
  28. 18
      libjsqrc/ethereumjs/test/db.methods.js
  29. 42
      libjsqrc/ethereumjs/test/eth.methods.js
  30. 2
      libjsqrc/ethereumjs/test/mocha.opts
  31. 19
      libjsqrc/ethereumjs/test/shh.methods.js
  32. 15
      libjsqrc/ethereumjs/test/utils.js
  33. 18
      libjsqrc/ethereumjs/test/web3.methods.js
  34. 12
      libjsqrc/js.qrc
  35. 2
      libp2p/Host.cpp
  36. 2
      libqethereum/QEthereum.h
  37. 1
      libweb3jsonrpc/WebThreeStubServer.h
  38. 11
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  39. 2
      libweb3jsonrpc/WebThreeStubServerBase.h
  40. 4
      libweb3jsonrpc/abstractwebthreestubserver.h
  41. 2
      libweb3jsonrpc/spec.json
  42. 12
      mix/MixClient.cpp
  43. 8
      mix/MixClient.h
  44. 6
      neth/main.cpp
  45. 61
      standard.js
  46. 23
      third/MainWin.cpp
  47. 8
      third/MainWin.h

1
CMakeLists.txt

@ -49,6 +49,7 @@ endfunction()
function(createBuildInfo)
# Set build platform; to be written to BuildInfo.h
set(ETH_BUILD_PLATFORM ${TARGET_PLATFORM})
if (CMAKE_COMPILER_IS_MINGW)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/mingw")
elseif (CMAKE_COMPILER_IS_MSYS)

12
alethzero/Main.ui

@ -173,6 +173,7 @@
<addaction name="enableOptimizer"/>
<addaction name="separator"/>
<addaction name="usePrivate"/>
<addaction name="jitvm"/>
</widget>
<widget class="QMenu" name="menu_View">
<property name="title">
@ -2055,6 +2056,17 @@ font-size: 14pt</string>
<string>Clear Pe&amp;nd&amp;ing</string>
</property>
</action>
<action name="jitvm">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>Use &amp;LLVM-EVM</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

38
alethzero/MainWin.cpp

@ -40,6 +40,7 @@
#include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libethereum/BlockChain.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Client.h>
@ -243,14 +244,14 @@ void Main::onKeysChanged()
installBalancesWatch();
}
unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function<void()> const& _f)
unsigned Main::installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf);
m_handlers[ret] = _f;
return ret;
}
unsigned Main::installWatch(dev::h256 _tf, std::function<void()> const& _f)
unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf);
m_handlers[ret] = _f;
@ -265,10 +266,10 @@ void Main::uninstallWatch(unsigned _w)
void Main::installWatches()
{
installWatch(dev::eth::LogFilter().address(c_newConfig), [=]() { installNameRegWatch(); });
installWatch(dev::eth::LogFilter().address(c_newConfig), [=]() { installCurrenciesWatch(); });
installWatch(dev::eth::PendingChangedFilter, [=](){ onNewPending(); });
installWatch(dev::eth::ChainChangedFilter, [=](){ onNewBlock(); });
installWatch(dev::eth::LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(dev::eth::LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(dev::eth::PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(dev::eth::ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
}
Address Main::getNameReg() const
@ -284,13 +285,13 @@ Address Main::getCurrencies() const
void Main::installNameRegWatch()
{
uninstallWatch(m_nameRegFilter);
m_nameRegFilter = installWatch(dev::eth::LogFilter().address((u160)getNameReg()), [=](){ onNameRegChange(); });
m_nameRegFilter = installWatch(dev::eth::LogFilter().address((u160)getNameReg()), [=](LocalisedLogEntries const&){ onNameRegChange(); });
}
void Main::installCurrenciesWatch()
{
uninstallWatch(m_currenciesFilter);
m_currenciesFilter = installWatch(dev::eth::LogFilter().address((u160)getCurrencies()), [=](){ onCurrenciesChange(); });
m_currenciesFilter = installWatch(dev::eth::LogFilter().address((u160)getCurrencies()), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
}
void Main::installBalancesWatch()
@ -308,7 +309,7 @@ void Main::installBalancesWatch()
tf.address(c).topic(h256(i.address(), h256::AlignRight));
uninstallWatch(m_balancesFilter);
m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); });
m_balancesFilter = installWatch(tf, [=](LocalisedLogEntries const&){ onBalancesChange(); });
}
void Main::onNameRegChange()
@ -644,6 +645,7 @@ void Main::writeSettings()
s.setValue("url", ui->urlEdit->text());
s.setValue("privateChain", m_privateChain);
s.setValue("verbosity", ui->verbosity->value());
s.setValue("jitvm", ui->jitvm->isChecked());
bytes d = m_webThree->saveNodes();
if (d.size())
@ -718,6 +720,7 @@ void Main::readSettings(bool _skipGeometry)
m_privateChain = s.value("privateChain", "").toString();
ui->usePrivate->setChecked(m_privateChain.size());
ui->verbosity->setValue(s.value("verbosity", 1).toInt());
ui->jitvm->setChecked(s.value("jitvm", true).toBool());
ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html
on_urlEdit_returnPressed();
@ -817,6 +820,12 @@ void Main::on_usePrivate_triggered()
on_killBlockchain_triggered();
}
void Main::on_jitvm_triggered()
{
bool jit = ui->jitvm->isChecked();
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
}
void Main::on_urlEdit_returnPressed()
{
QString s = ui->urlEdit->text();
@ -1162,8 +1171,11 @@ void Main::timerEvent(QTimerEvent*)
m_qweb->poll();
for (auto const& i: m_handlers)
if (ethereum()->checkWatch(i.first))
i.second();
{
auto ls = ethereum()->checkWatch(i.first);
if (ls.size())
i.second(ls);
}
}
string Main::renderDiff(dev::eth::StateDiff const& _d) const
@ -1265,7 +1277,7 @@ void Main::on_transactionQueue_currentItemChanged()
auto r = receipt.rlp();
s << "<div>Receipt: " << toString(RLP(r)) << "</div>";
s << "<div>Receipt-Hex: <span style=\"font-family: Monospace,Lucida Console,Courier,Courier New,sans-serif; font-size: small\">" << toHex(receipt.rlp()) << "</span></div>";
s << renderDiff(ethereum()->diff(i, -1));
s << renderDiff(ethereum()->diff(i, 0));
// s << "Pre: " << fs.rootHash() << "<br/>";
// s << "Post: <b>" << ts.rootHash() << "</b>";
}
@ -1802,8 +1814,6 @@ void Main::on_net_triggered()
web3()->setClientVersion(n);
if (ui->net->isChecked())
{
// TODO: alter network stuff?
//ui->port->value(), string(), 0, NodeMode::Full, ui->idealPeers->value(), ui->forceAddress->text().toStdString(), ui->upnp->isChecked(), m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0
web3()->setIdealPeerCount(ui->idealPeers->value());
web3()->setNetworkPreferences(netPrefs());
ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0);

9
alethzero/MainWin.h

@ -66,6 +66,8 @@ struct WorldState
std::vector<WorldState const*> levels;
};
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
class Main : public QMainWindow
{
Q_OBJECT
@ -156,6 +158,7 @@ private slots:
void on_importKeyFile_triggered();
void on_post_clicked();
void on_newIdentity_triggered();
void on_jitvm_triggered();
void refreshWhisper();
void refreshBlockChain();
@ -194,8 +197,8 @@ private:
dev::u256 value() const;
dev::u256 gasPrice() const;
unsigned installWatch(dev::eth::LogFilter const& _tf, std::function<void()> const& _f);
unsigned installWatch(dev::h256 _tf, std::function<void()> const& _f);
unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f);
unsigned installWatch(dev::h256 _tf, WatchHandler const& _f);
void uninstallWatch(unsigned _w);
void keysChanged();
@ -228,7 +231,7 @@ private:
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::map<unsigned, std::function<void()>> m_handlers;
std::map<unsigned, WatchHandler> m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;

6
eth/main.cpp

@ -180,6 +180,12 @@ void sighandler(int)
g_exit = true;
}
enum class NodeMode
{
PeerServer,
Full
};
int main(int argc, char** argv)
{
unsigned short listenPort = 30303;

3
libdevcrypto/Common.cpp

@ -23,6 +23,7 @@
#include <random>
#include <chrono>
#include <mutex>
#include <libdevcore/Guards.h>
#include "SHA3.h"
#include "FileSystem.h"
#include "CryptoPP.h"
@ -139,7 +140,7 @@ h256 Nonce::get(bool _commit)
static h256 s_seed;
static string s_seedFile(getDataDir() + "/seed");
static mutex s_x;
lock_guard<mutex> l(s_x);
Guard l(s_x);
if (!s_seed)
{
static Nonce s_nonce;

17
libdevcrypto/CryptoPP.cpp

@ -20,6 +20,7 @@
*/
#include "CryptoPP.h"
#include <libdevcore/Guards.h>
using namespace std;
using namespace dev;
@ -40,7 +41,7 @@ void Secp256k1::encrypt(Public const& _k, bytes& io_cipher)
ciphertext.resize(e.CiphertextLength(plen));
{
lock_guard<mutex> l(x_rng);
Guard l(x_rng);
e.Encrypt(m_rng, io_cipher.data(), plen, ciphertext.data());
}
@ -65,7 +66,7 @@ void Secp256k1::decrypt(Secret const& _k, bytes& io_text)
DecodingResult r;
{
lock_guard<mutex> l(x_rng);
Guard l(x_rng);
r = d.Decrypt(m_rng, io_text.data(), clen, plain.data());
}
@ -99,7 +100,7 @@ Signature Secp256k1::sign(Secret const& _key, h256 const& _hash)
ECP::Point rp;
Integer r;
{
lock_guard<mutex> l(x_params);
Guard l(x_params);
rp = m_params.ExponentiateBase(k);
r = m_params.ConvertElementToInteger(rp);
}
@ -149,7 +150,7 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
ECP::Element x;
{
lock_guard<mutex> l(x_curve);
Guard l(x_curve);
m_curve.DecodePoint(x, encodedpoint, 33);
if (!m_curve.VerifyPoint(x))
return recovered;
@ -158,7 +159,7 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
// if (_signature[64] & 2)
// {
// r += m_q;
// lock_guard<mutex> l(x_params);
// Guard l(x_params);
// if (r >= m_params.GetMaxExponent())
// return recovered;
// }
@ -171,7 +172,7 @@ Public Secp256k1::recover(Signature _signature, bytesConstRef _message)
ECP::Point p;
byte recoveredbytes[65];
{
lock_guard<mutex> l(x_curve);
Guard l(x_curve);
// todo: make generator member
p = m_curve.CascadeMultiply(u2, x, u1, m_params.GetSubgroupGenerator());
m_curve.EncodePoint(recoveredbytes, p, false);
@ -210,7 +211,7 @@ void Secp256k1::exportPublicKey(CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> const&
bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
{
lock_guard<mutex> l(x_params);
Guard l(x_params);
m_params.GetCurve().EncodePoint(prefixedKey.data(), _k.GetPublicElement(), false);
assert(Public::size + 1 == _k.GetGroupParameters().GetEncodedElementSize(true));
}
@ -223,7 +224,7 @@ void Secp256k1::exponentToPublic(Integer const& _e, Public& o_p)
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pk;
{
lock_guard<mutex> l(x_params);
Guard l(x_params);
pk.Initialize(m_params, m_params.ExponentiateBase(_e));
}

127
libethereum/Client.cpp

@ -159,9 +159,10 @@ void Client::clearPending()
WriteGuard l(x_stateDB);
if (!m_postMine.pending().size())
return;
for (unsigned i = 0; i < m_postMine.pending().size(); ++i)
appendFromNewPending(m_postMine.logBloom(i), changeds);
// for (unsigned i = 0; i < m_postMine.pending().size(); ++i)
// appendFromNewPending(m_postMine.logBloom(i), changeds);
changeds.insert(PendingChangedFilter);
m_tq.clear();
m_postMine = m_preMine;
}
@ -176,21 +177,29 @@ void Client::clearPending()
unsigned Client::installWatch(h256 _h)
{
auto ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
m_watches[ret] = ClientWatch(_h);
cwatch << "+++" << ret << _h;
unsigned ret;
{
Guard l(m_filterLock);
ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
m_watches[ret] = ClientWatch(_h);
cwatch << "+++" << ret << _h;
}
auto ch = logs(ret);
{
Guard l(m_filterLock);
swap(m_watches[ret].changes, ch);
}
return ret;
}
unsigned Client::installWatch(LogFilter const& _f)
{
lock_guard<mutex> l(m_filterLock);
h256 h = _f.sha3();
if (!m_filters.count(h))
m_filters.insert(make_pair(h, _f));
{
Guard l(m_filterLock);
if (!m_filters.count(h))
m_filters.insert(make_pair(h, _f));
}
return installWatch(h);
}
@ -198,7 +207,7 @@ void Client::uninstallWatch(unsigned _i)
{
cwatch << "XXX" << _i;
lock_guard<mutex> l(m_filterLock);
Guard l(m_filterLock);
auto it = m_watches.find(_i);
if (it == m_watches.end())
@ -214,33 +223,82 @@ void Client::uninstallWatch(unsigned _i)
void Client::noteChanged(h256Set const& _filters)
{
lock_guard<mutex> l(m_filterLock);
Guard l(m_filterLock);
// accrue all changes left in each filter into the watches.
for (auto& i: m_watches)
if (_filters.count(i.second.id))
{
// cwatch << "!!!" << i.first << i.second.id;
i.second.changes++;
try {
i.second.changes += m_filters.at(i.second.id).changes;
} catch(...){}
}
// clear the filters now.
for (auto& i: m_filters)
i.second.changes.clear();
}
void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const
LocalisedLogEntries Client::peekWatch(unsigned _watchId) const
{
// TODO: more precise check on whether the txs match.
lock_guard<mutex> l(m_filterLock);
for (pair<h256, InstalledFilter> const& i: m_filters)
if ((unsigned)i.second.filter.latest() > m_bc.number() && i.second.filter.matches(_bloom))
o_changed.insert(i.first);
Guard l(m_filterLock);
try {
return m_watches.at(_watchId).changes;
} catch (...) {}
return LocalisedLogEntries();
}
void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const
LocalisedLogEntries Client::checkWatch(unsigned _watchId)
{
Guard l(m_filterLock);
LocalisedLogEntries ret;
try {
std::swap(ret, m_watches.at(_watchId).changes);
} catch (...) {}
return ret;
}
void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed)
{
Guard l(m_filterLock);
for (pair<h256 const, InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() > m_bc.number())
{
// acceptable number.
auto m = i.second.filter.matches(_receipt);
if (m.size())
{
// filter catches them
for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1));
io_changed.insert(i.first);
}
}
}
void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
{
// TODO: more precise check on whether the txs match.
auto d = m_bc.info(_block);
auto br = m_bc.receipts(_block);
lock_guard<mutex> l(m_filterLock);
for (pair<h256, InstalledFilter> const& i: m_filters)
Guard l(m_filterLock);
for (pair<h256 const, InstalledFilter>& i: m_filters)
if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom))
o_changed.insert(i.first);
// acceptable number & looks like block may contain a matching log entry.
for (TransactionReceipt const& tr: br.receipts)
{
auto m = i.second.filter.matches(tr);
if (m.size())
{
// filter catches them
for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number));
io_changed.insert(i.first);
}
}
}
void Client::setForceMining(bool _enable)
@ -467,10 +525,10 @@ void Client::doWork()
// returns h256s as blooms, once for each transaction.
cwork << "postSTATE <== TQ";
h512s newPendingBlooms = m_postMine.sync(m_bc, m_tq);
if (newPendingBlooms.size())
TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq);
if (newPendingReceipts.size())
{
for (auto i: newPendingBlooms)
for (auto i: newPendingReceipts)
appendFromNewPending(i, changeds);
changeds.insert(PendingChangedFilter);
@ -591,16 +649,16 @@ BlockInfo Client::uncle(h256 _blockHash, unsigned _i) const
return BlockInfo::fromHeader(b[2][_i].data());
}
LogEntries Client::logs(LogFilter const& _f) const
LocalisedLogEntries Client::logs(LogFilter const& _f) const
{
LogEntries ret;
unsigned begin = min<unsigned>(m_bc.number(), (unsigned)_f.latest());
unsigned end = min(begin, (unsigned)_f.earliest());
LocalisedLogEntries ret;
unsigned begin = min<unsigned>(m_bc.number() + 1, (unsigned)_f.latest());
unsigned end = min(m_bc.number(), min(begin, (unsigned)_f.earliest()));
unsigned m = _f.max();
unsigned s = _f.skip();
// Handle pending transactions differently as they're not on the block chain.
if (begin == m_bc.number())
if (begin > m_bc.number())
{
ReadGuard l(x_stateDB);
for (unsigned i = 0; i < m_postMine.pending().size(); ++i)
@ -614,9 +672,10 @@ LogEntries Client::logs(LogFilter const& _f) const
if (s)
s--;
else
ret.insert(ret.begin(), le[j]);
ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin));
}
}
begin = m_bc.number();
}
#if ETH_DEBUG
@ -648,7 +707,7 @@ LogEntries Client::logs(LogFilter const& _f) const
if (s)
s--;
else
ret.insert(ret.begin(), le[j]);
ret.insert(ret.begin(), LocalisedLogEntry(le[j], n));
}
}
}

33
libethereum/Client.h

@ -57,12 +57,6 @@ enum ClientWorkState
Deleted
};
enum class NodeMode
{
PeerServer,
Full
};
class VersionChecker
{
public:
@ -84,6 +78,7 @@ struct InstalledFilter
LogFilter filter;
unsigned refCount = 1;
LocalisedLogEntries changes;
};
static const h256 PendingChangedFilter = u256(0);
@ -95,7 +90,7 @@ struct ClientWatch
explicit ClientWatch(h256 _id): id(_id) {}
h256 id;
unsigned changes = 1;
LocalisedLogEntries changes;
};
struct WatchChannel: public LogChannel { static const char* name() { return "(o)"; } static const int verbosity = 7; };
@ -108,9 +103,9 @@ struct WorkChannel: public LogChannel { static const char* name() { return "-W-"
#define cworkout dev::LogOutputStream<dev::eth::WorkOutChannel, true>()
template <class T> struct ABISerialiser {};
template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> const& _t) { return _t.asBytes(); } };
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(); } };
template <> struct ABISerialiser<u160> { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } };
template <> struct ABISerialiser<u160> { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } };
template <> struct ABISerialiser<string32> { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } };
inline bytes abiInAux() { return {}; }
@ -125,9 +120,9 @@ template <class ... T> bytes abiIn(std::string _id, T const& ... _t)
}
template <class T> struct ABIDeserialiser {};
template <unsigned N> struct ABIDeserialiser<FixedHash<N>> { static FixedHash<N> deserialise(bytesConstRef& io_t) { FixedHash<N> ret; io_t.cropped(0, N).populate(ret.ref()); return ret; } };
template <unsigned N> struct ABIDeserialiser<FixedHash<N>> { static FixedHash<N> deserialise(bytesConstRef& io_t) { static_assert(N <= 32, "Parameter sizes must be at most 32 bytes."); FixedHash<N> ret; io_t.cropped(32 - N, N).populate(ret.ref()); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<u256> { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian<u256>(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<u160> { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian<u160>(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } };
template <> struct ABIDeserialiser<u160> { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian<u160>(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<string32> { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).populate(vector_ref<char>(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } };
template <class T> T abiOut(bytes const& _data)
@ -188,11 +183,11 @@ public:
virtual unsigned installWatch(LogFilter const& _filter);
virtual unsigned installWatch(h256 _filterId);
virtual void uninstallWatch(unsigned _watchId);
virtual bool peekWatch(unsigned _watchId) const { std::lock_guard<std::mutex> l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } }
virtual bool checkWatch(unsigned _watchId) { std::lock_guard<std::mutex> l(m_filterLock); bool ret = false; try { ret = m_watches.at(_watchId).changes != 0; m_watches.at(_watchId).changes = 0; } catch (...) {} return ret; }
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const;
virtual LocalisedLogEntries checkWatch(unsigned _watchId);
virtual LogEntries logs(unsigned _watchId) const { try { std::lock_guard<std::mutex> l(m_filterLock); return logs(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return LogEntries(); } }
virtual LogEntries logs(LogFilter const& _filter) const;
virtual LocalisedLogEntries logs(unsigned _watchId) const { try { Guard l(m_filterLock); return logs(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return LocalisedLogEntries(); } }
virtual LocalisedLogEntries logs(LogFilter const& _filter) const;
// [EXTRA API]:
@ -292,11 +287,11 @@ private:
/// Collate the changed filters for the bloom filter of the given pending transaction.
/// Insert any filters that are activated into @a o_changed.
void appendFromNewPending(LogBloom _pendingTransactionBloom, h256Set& o_changed) const;
void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed);
/// Collate the changed filters for the hash of the given block.
/// Insert any filters that are activated into @a o_changed.
void appendFromNewBlock(h256 _blockHash, h256Set& o_changed) const;
void appendFromNewBlock(h256 const& _blockHash, h256Set& io_changed);
/// Record that the set of filters @a _filters have changed.
/// This doesn't actually make any callbacks, but incrememnts some counters in m_watches.
@ -313,7 +308,7 @@ private:
TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain.
BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported).
mutable boost::shared_mutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine.
mutable SharedMutex x_stateDB; ///< Lock on the state DB, effectively a lock on m_postMine.
OverlayDB m_stateDB; ///< Acts as the central point for the state database, so multiple States can share it.
State m_preMine; ///< The present state of the client.
State m_postMine; ///< The state of the client which we're mining (i.e. it'll have all the rewards added).
@ -321,7 +316,7 @@ private:
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::vector<Miner> m_miners;
mutable boost::shared_mutex x_miners;
mutable SharedMutex x_miners;
bool m_paranoia = false; ///< Should we be paranoid about our state?
bool m_turboMining = false; ///< Don't squander all of our time mining actually just sleeping.
bool m_forceMining = false; ///< Mine even when there are no transactions pending?

2
libethereum/EthereumPeer.cpp

@ -317,6 +317,8 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
disable("Blacklisted client version.");
else if (host()->isBanned(session()->id()))
disable("Peer banned for previous bad behaviour.");
else
transition(Asking::Nothing);
break;
}
case GetTransactionsPacket: break; // DEPRECATED.

15
libethereum/Interface.h

@ -86,15 +86,15 @@ public:
// [LOGS API]
virtual LogEntries logs(unsigned _watchId) const = 0;
virtual LogEntries logs(LogFilter const& _filter) const = 0;
virtual LocalisedLogEntries logs(unsigned _watchId) const = 0;
virtual LocalisedLogEntries logs(LogFilter const& _filter) const = 0;
/// Install, uninstall and query watches.
virtual unsigned installWatch(LogFilter const& _filter) = 0;
virtual unsigned installWatch(h256 _filterId) = 0;
virtual void uninstallWatch(unsigned _watchId) = 0;
virtual bool peekWatch(unsigned _watchId) const = 0;
virtual bool checkWatch(unsigned _watchId) = 0;
virtual LocalisedLogEntries peekWatch(unsigned _watchId) const = 0;
virtual LocalisedLogEntries checkWatch(unsigned _watchId) = 0;
// [BLOCK QUERY API]
@ -178,10 +178,9 @@ public:
Watch(Interface& _c, LogFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {}
~Watch() { if (m_c) m_c->uninstallWatch(m_id); }
bool check() { return m_c ? m_c->checkWatch(m_id) : false; }
bool peek() { return m_c ? m_c->peekWatch(m_id) : false; }
// PastMessages messages() const { return m_c->messages(m_id); }
LogEntries logs() const { return m_c->logs(m_id); }
LocalisedLogEntries check() { return m_c ? m_c->checkWatch(m_id) : LocalisedLogEntries(); }
LocalisedLogEntries peek() { return m_c ? m_c->peekWatch(m_id) : LocalisedLogEntries(); }
LocalisedLogEntries logs() const { return m_c->logs(m_id); }
private:
Interface* m_c = nullptr;

17
libethereum/LogFilter.cpp

@ -68,14 +68,15 @@ bool LogFilter::matches(State const& _s, unsigned _i) const
LogEntries LogFilter::matches(TransactionReceipt const& _m) const
{
LogEntries ret;
for (LogEntry const& e: _m.log())
{
if (!m_addresses.empty() && !m_addresses.count(e.address))
continue;
for (auto const& t: m_topics)
if (!std::count(e.topics.begin(), e.topics.end(), t))
if (matches(_m.bloom()))
for (LogEntry const& e: _m.log())
{
if (!m_addresses.empty() && !m_addresses.count(e.address))
continue;
ret.push_back(e);
}
for (auto const& t: m_topics)
if (!std::count(e.topics.begin(), e.topics.end(), t))
continue;
ret.push_back(e);
}
return ret;
}

6
libethereum/State.cpp

@ -412,10 +412,10 @@ bool State::cull(TransactionQueue& _tq) const
return ret;
}
h512s State::sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged)
TransactionReceipts State::sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged)
{
// TRANSACTIONS
h512s ret;
TransactionReceipts ret;
auto ts = _tq.transactions();
auto lh = getLastHashes(_bc);
@ -432,7 +432,7 @@ h512s State::sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transact
uncommitToMine();
// boost::timer t;
execute(lh, i.second);
ret.push_back(m_receipts.back().bloom());
ret.push_back(m_receipts.back());
_tq.noteGood(i);
++goodTxs;
// cnote << "TX took:" << t.elapsed() * 1000;

4
libethereum/State.h

@ -140,10 +140,10 @@ public:
// TODO: Cleaner interface.
/// Sync our transactions, killing those from the queue that we have and assimilating those that we don't.
/// @returns a list of bloom filters one for each transaction placed from the queue into the state.
/// @returns a list of receipts one for each transaction placed from the queue into the state.
/// @a o_transactionQueueChanged boolean pointer, the value of which will be set to true if the transaction queue
/// changed and the pointer is non-null
h512s sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr);
TransactionReceipts sync(BlockChain const& _bc, TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr);
/// Like sync but only operate on _tq, killing the invalid/old ones.
bool cull(TransactionQueue& _tq) const;

17
libethereum/Utility.cpp

@ -23,6 +23,7 @@
#include <boost/regex.hpp>
#include <libethcore/CommonEth.h>
#include <libdevcrypto/SHA3.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -32,7 +33,7 @@ bytes dev::eth::parseData(string const& _args)
bytes m_data;
boost::smatch what;
static const boost::regex r("(@|\\$)?\"([^\"]*)\"(\\s.*)?");
static const boost::regex r("(!|#|@|\\$)?\"([^\"]*)\"(\\s.*)?");
static const boost::regex d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?");
static const boost::regex h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?");
@ -67,13 +68,15 @@ bytes dev::eth::parseData(string const& _args)
}
else if (boost::regex_match(s, what, r))
{
for (auto i: (string)what[2])
m_data.push_back((byte)i);
if (what[1] != "$")
for (int i = what[2].length(); i < 32; ++i)
m_data.push_back(0);
bytes d = asBytes(what[2]);
if (what[1] == "!")
m_data += FixedHash<4>(sha3(d)).asBytes();
else if (what[1] == "#")
m_data += sha3(d).asBytes();
else if (what[1] == "$")
m_data += d + bytes{0};
else
m_data.push_back(0);
m_data += d + bytes(32 - what[2].length() % 32, 0);
s = what[3];
}
else

10
libevm/ExtVMFace.h

@ -60,6 +60,16 @@ struct LogEntry
using LogEntries = std::vector<LogEntry>;
struct LocalisedLogEntry: public LogEntry
{
LocalisedLogEntry() {}
LocalisedLogEntry(LogEntry const& _le, unsigned _number): LogEntry(_le), number(_number) {}
unsigned number = 0;
};
using LocalisedLogEntries = std::vector<LocalisedLogEntry>;
inline LogBloom bloom(LogEntries const& _logs)
{
LogBloom ret;

760
libevm/VM.cpp

@ -31,3 +31,763 @@ void VM::reset(u256 _gas) noexcept
m_curPC = 0;
m_jumpDests.clear();
}
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
if (m_jumpDests.empty())
for (unsigned i = 0; i < _ext.code.size(); ++i)
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.insert(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
u256 nextPC = m_curPC + 1;
auto osteps = _steps;
for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1)
{
// INSTRUCTION...
Instruction inst = (Instruction)_ext.getCode(m_curPC);
// FEES...
bigint runGas = c_stepGas;
bigint newTempSize = m_temp.size();
bigint copySize = 0;
auto onOperation = [&]()
{
if (_onOp)
_onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
};
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
switch (inst)
{
case Instruction::STOP:
runGas = 0;
break;
case Instruction::SUICIDE:
require(1);
runGas = 0;
break;
case Instruction::SSTORE:
require(2);
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
runGas = 0;
_ext.sub.refunds += c_sstoreRefundGas;
}
else
runGas = c_sstoreResetGas;
break;
case Instruction::SLOAD:
require(1);
runGas = c_sloadGas;
break;
// These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE:
require(2);
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::MSTORE8:
require(2);
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
require(1);
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
require(2);
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
require(2);
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
require(4);
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
case Instruction::BALANCE:
require(1);
runGas = c_balanceGas;
break;
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
require(n + 2);
runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break;
}
case Instruction::CALL:
case Instruction::CALLCODE:
require(7);
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break;
case Instruction::CREATE:
{
require(3);
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
require(2);
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
case Instruction::BLOCKHASH:
require(1);
break;
case Instruction::PC:
case Instruction::MSIZE:
case Instruction::GAS:
case Instruction::JUMPDEST:
case Instruction::ADDRESS:
case Instruction::ORIGIN:
case Instruction::CALLER:
case Instruction::CALLVALUE:
case Instruction::CALLDATASIZE:
case Instruction::CODESIZE:
case Instruction::GASPRICE:
case Instruction::COINBASE:
case Instruction::TIMESTAMP:
case Instruction::NUMBER:
case Instruction::DIFFICULTY:
case Instruction::GASLIMIT:
case Instruction::PUSH1:
case Instruction::PUSH2:
case Instruction::PUSH3:
case Instruction::PUSH4:
case Instruction::PUSH5:
case Instruction::PUSH6:
case Instruction::PUSH7:
case Instruction::PUSH8:
case Instruction::PUSH9:
case Instruction::PUSH10:
case Instruction::PUSH11:
case Instruction::PUSH12:
case Instruction::PUSH13:
case Instruction::PUSH14:
case Instruction::PUSH15:
case Instruction::PUSH16:
case Instruction::PUSH17:
case Instruction::PUSH18:
case Instruction::PUSH19:
case Instruction::PUSH20:
case Instruction::PUSH21:
case Instruction::PUSH22:
case Instruction::PUSH23:
case Instruction::PUSH24:
case Instruction::PUSH25:
case Instruction::PUSH26:
case Instruction::PUSH27:
case Instruction::PUSH28:
case Instruction::PUSH29:
case Instruction::PUSH30:
case Instruction::PUSH31:
case Instruction::PUSH32:
break;
case Instruction::NOT:
case Instruction::ISZERO:
case Instruction::CALLDATALOAD:
case Instruction::EXTCODESIZE:
case Instruction::POP:
case Instruction::JUMP:
require(1);
break;
case Instruction::ADD:
case Instruction::MUL:
case Instruction::SUB:
case Instruction::DIV:
case Instruction::SDIV:
case Instruction::MOD:
case Instruction::SMOD:
case Instruction::LT:
case Instruction::GT:
case Instruction::SLT:
case Instruction::SGT:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
case Instruction::BYTE:
case Instruction::JUMPI:
case Instruction::SIGNEXTEND:
require(2);
break;
case Instruction::ADDMOD:
case Instruction::MULMOD:
require(3);
break;
case Instruction::DUP1:
case Instruction::DUP2:
case Instruction::DUP3:
case Instruction::DUP4:
case Instruction::DUP5:
case Instruction::DUP6:
case Instruction::DUP7:
case Instruction::DUP8:
case Instruction::DUP9:
case Instruction::DUP10:
case Instruction::DUP11:
case Instruction::DUP12:
case Instruction::DUP13:
case Instruction::DUP14:
case Instruction::DUP15:
case Instruction::DUP16:
require(1 + (int)inst - (int)Instruction::DUP1);
break;
case Instruction::SWAP1:
case Instruction::SWAP2:
case Instruction::SWAP3:
case Instruction::SWAP4:
case Instruction::SWAP5:
case Instruction::SWAP6:
case Instruction::SWAP7:
case Instruction::SWAP8:
case Instruction::SWAP9:
case Instruction::SWAP10:
case Instruction::SWAP11:
case Instruction::SWAP12:
case Instruction::SWAP13:
case Instruction::SWAP14:
case Instruction::SWAP15:
case Instruction::SWAP16:
require((int)inst - (int)Instruction::SWAP1 + 2);
break;
default:
BOOST_THROW_EXCEPTION(BadInstruction());
}
newTempSize = (newTempSize + 31) / 32 * 32;
if (newTempSize > m_temp.size())
runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32;
runGas += c_copyGas * (copySize + 31) / 32;
onOperation();
// if (_onOp)
// _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
if (m_gas < runGas)
{
// Out of gas!
m_gas = 0;
BOOST_THROW_EXCEPTION(OutOfGas());
}
m_gas = (u256)((bigint)m_gas - runGas);
if (newTempSize > m_temp.size())
m_temp.resize((size_t)newTempSize);
// EXECUTE...
switch (inst)
{
case Instruction::ADD:
//pops two items and pushes S[-1] + S[-2] mod 2^256.
m_stack[m_stack.size() - 2] += m_stack.back();
m_stack.pop_back();
break;
case Instruction::MUL:
//pops two items and pushes S[-1] * S[-2] mod 2^256.
m_stack[m_stack.size() - 2] *= m_stack.back();
m_stack.pop_back();
break;
case Instruction::SUB:
m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::DIV:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() / m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back();
break;
case Instruction::SDIV:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back();
break;
case Instruction::MOD:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() % m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back();
break;
case Instruction::SMOD:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back();
break;
case Instruction::EXP:
{
auto base = m_stack.back();
auto expon = m_stack[m_stack.size() - 2];
m_stack.pop_back();
m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256);
break;
}
case Instruction::NOT:
m_stack.back() = ~m_stack.back();
break;
case Instruction::LT:
m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::GT:
m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::SLT:
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::SGT:
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::EQ:
m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::ISZERO:
m_stack.back() = m_stack.back() ? 0 : 1;
break;
case Instruction::AND:
m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::OR:
m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::XOR:
m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::BYTE:
m_stack[m_stack.size() - 2] = m_stack.back() < 32 ? (m_stack[m_stack.size() - 2] >> (unsigned)(8 * (31 - m_stack.back()))) & 0xff : 0;
m_stack.pop_back();
break;
case Instruction::ADDMOD:
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) + bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::MULMOD:
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) * bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::SIGNEXTEND:
if (m_stack.back() < 31)
{
unsigned const testBit(m_stack.back() * 8 + 7);
u256& number = m_stack[m_stack.size() - 2];
u256 mask = ((u256(1) << testBit) - 1);
if (boost::multiprecision::bit_test(number, testBit))
number |= ~mask;
else
number &= mask;
}
m_stack.pop_back();
break;
case Instruction::SHA3:
{
unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back();
m_stack.pop_back();
m_stack.push_back(sha3(bytesConstRef(m_temp.data() + inOff, inSize)));
break;
}
case Instruction::ADDRESS:
m_stack.push_back(fromAddress(_ext.myAddress));
break;
case Instruction::ORIGIN:
m_stack.push_back(fromAddress(_ext.origin));
break;
case Instruction::BALANCE:
{
m_stack.back() = _ext.balance(asAddress(m_stack.back()));
break;
}
case Instruction::CALLER:
m_stack.push_back(fromAddress(_ext.caller));
break;
case Instruction::CALLVALUE:
m_stack.push_back(_ext.value);
break;
case Instruction::CALLDATALOAD:
{
if ((unsigned)m_stack.back() + (uint64_t)31 < _ext.data.size())
m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back());
else
{
h256 r;
for (uint64_t i = (unsigned)m_stack.back(), e = (unsigned)m_stack.back() + (uint64_t)32, j = 0; i < e; ++i, ++j)
r[j] = i < _ext.data.size() ? _ext.data[i] : 0;
m_stack.back() = (u256)r;
}
break;
}
case Instruction::CALLDATASIZE:
m_stack.push_back(_ext.data.size());
break;
case Instruction::CODESIZE:
m_stack.push_back(_ext.code.size());
break;
case Instruction::EXTCODESIZE:
m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size();
break;
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::EXTCODECOPY:
{
Address a;
if (inst == Instruction::EXTCODECOPY)
{
a = asAddress(m_stack.back());
m_stack.pop_back();
}
unsigned offset = (unsigned)m_stack.back();
m_stack.pop_back();
u256 index = m_stack.back();
m_stack.pop_back();
unsigned size = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned sizeToBeCopied;
switch(inst)
{
case Instruction::CALLDATACOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.data.size() ? (u256)_ext.data.size() < index ? 0 : _ext.data.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.data.data() + (unsigned)index, sizeToBeCopied);
break;
case Instruction::CODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.code.size() ? (u256)_ext.code.size() < index ? 0 : _ext.code.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.code.data() + (unsigned)index, sizeToBeCopied);
break;
case Instruction::EXTCODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < index ? 0 : _ext.codeAt(a).size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.codeAt(a).data() + (unsigned)index, sizeToBeCopied);
break;
default:
// this is unreachable, but if someone introduces a bug in the future, he may get here.
assert(false);
BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested."));
break;
}
memset(m_temp.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied);
break;
}
case Instruction::GASPRICE:
m_stack.push_back(_ext.gasPrice);
break;
case Instruction::BLOCKHASH:
m_stack.back() = (u256)_ext.blockhash(m_stack.back());
break;
case Instruction::COINBASE:
m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress);
break;
case Instruction::TIMESTAMP:
m_stack.push_back(_ext.currentBlock.timestamp);
break;
case Instruction::NUMBER:
m_stack.push_back(_ext.currentBlock.number);
break;
case Instruction::DIFFICULTY:
m_stack.push_back(_ext.currentBlock.difficulty);
break;
case Instruction::GASLIMIT:
m_stack.push_back(1000000);
break;
case Instruction::PUSH1:
case Instruction::PUSH2:
case Instruction::PUSH3:
case Instruction::PUSH4:
case Instruction::PUSH5:
case Instruction::PUSH6:
case Instruction::PUSH7:
case Instruction::PUSH8:
case Instruction::PUSH9:
case Instruction::PUSH10:
case Instruction::PUSH11:
case Instruction::PUSH12:
case Instruction::PUSH13:
case Instruction::PUSH14:
case Instruction::PUSH15:
case Instruction::PUSH16:
case Instruction::PUSH17:
case Instruction::PUSH18:
case Instruction::PUSH19:
case Instruction::PUSH20:
case Instruction::PUSH21:
case Instruction::PUSH22:
case Instruction::PUSH23:
case Instruction::PUSH24:
case Instruction::PUSH25:
case Instruction::PUSH26:
case Instruction::PUSH27:
case Instruction::PUSH28:
case Instruction::PUSH29:
case Instruction::PUSH30:
case Instruction::PUSH31:
case Instruction::PUSH32:
{
int i = (int)inst - (int)Instruction::PUSH1 + 1;
nextPC = m_curPC + 1;
m_stack.push_back(0);
for (; i--; nextPC++)
m_stack.back() = (m_stack.back() << 8) | _ext.getCode(nextPC);
break;
}
case Instruction::POP:
m_stack.pop_back();
break;
case Instruction::DUP1:
case Instruction::DUP2:
case Instruction::DUP3:
case Instruction::DUP4:
case Instruction::DUP5:
case Instruction::DUP6:
case Instruction::DUP7:
case Instruction::DUP8:
case Instruction::DUP9:
case Instruction::DUP10:
case Instruction::DUP11:
case Instruction::DUP12:
case Instruction::DUP13:
case Instruction::DUP14:
case Instruction::DUP15:
case Instruction::DUP16:
{
auto n = 1 + (int)inst - (int)Instruction::DUP1;
m_stack.push_back(m_stack[m_stack.size() - n]);
break;
}
case Instruction::SWAP1:
case Instruction::SWAP2:
case Instruction::SWAP3:
case Instruction::SWAP4:
case Instruction::SWAP5:
case Instruction::SWAP6:
case Instruction::SWAP7:
case Instruction::SWAP8:
case Instruction::SWAP9:
case Instruction::SWAP10:
case Instruction::SWAP11:
case Instruction::SWAP12:
case Instruction::SWAP13:
case Instruction::SWAP14:
case Instruction::SWAP15:
case Instruction::SWAP16:
{
unsigned n = (int)inst - (int)Instruction::SWAP1 + 2;
auto d = m_stack.back();
m_stack.back() = m_stack[m_stack.size() - n];
m_stack[m_stack.size() - n] = d;
break;
}
case Instruction::MLOAD:
{
m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back());
break;
}
case Instruction::MSTORE:
{
*(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2];
m_stack.pop_back();
m_stack.pop_back();
break;
}
case Instruction::MSTORE8:
{
m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff);
m_stack.pop_back();
m_stack.pop_back();
break;
}
case Instruction::SLOAD:
m_stack.back() = _ext.store(m_stack.back());
break;
case Instruction::SSTORE:
_ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::JUMP:
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
BOOST_THROW_EXCEPTION(BadJumpDestination());
m_stack.pop_back();
break;
case Instruction::JUMPI:
if (m_stack[m_stack.size() - 2])
{
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
BOOST_THROW_EXCEPTION(BadJumpDestination());
}
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::PC:
m_stack.push_back(m_curPC);
break;
case Instruction::MSIZE:
m_stack.push_back(m_temp.size());
break;
case Instruction::GAS:
m_stack.push_back(m_gas);
break;
case Instruction::JUMPDEST:
break;
/* case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG1:
_ext.log({m_stack[m_stack.size() - 1]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 2], (unsigned)m_stack[m_stack.size() - 3]));
break;
case Instruction::LOG2:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 3], (unsigned)m_stack[m_stack.size() - 4]));
break;
case Instruction::LOG3:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 4], (unsigned)m_stack[m_stack.size() - 5]));
break;
case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6]));
break;*/
case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG1:
_ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG2:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG3:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::CREATE:
{
u256 endowment = m_stack.back();
m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned initSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024)
{
_ext.subBalance(endowment);
m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp));
}
else
m_stack.push_back(0);
break;
}
case Instruction::CALL:
case Instruction::CALLCODE:
{
u256 gas = m_stack.back();
m_stack.pop_back();
Address receiveAddress = asAddress(m_stack.back());
m_stack.pop_back();
u256 value = m_stack.back();
m_stack.pop_back();
unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned outOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned outSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024)
{
_ext.subBalance(value);
m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress));
}
else
m_stack.push_back(0);
m_gas += gas;
break;
}
case Instruction::RETURN:
{
unsigned b = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned s = (unsigned)m_stack.back();
m_stack.pop_back();
return bytesConstRef(m_temp.data() + b, s);
}
case Instruction::SUICIDE:
{
Address dest = asAddress(m_stack.back());
_ext.suicide(dest);
// ...follow through to...
}
case Instruction::STOP:
return bytesConstRef();
}
}
if (_steps == (uint64_t)-1)
BOOST_THROW_EXCEPTION(StepsDone());
return bytesConstRef();
}

761
libevm/VM.h

@ -77,766 +77,5 @@ private:
std::function<void()> m_onFail;
};
// TODO: Move it to cpp file. Not done to make review easier.
inline bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
auto memNeed = [](dev::u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
if (m_jumpDests.empty())
for (unsigned i = 0; i < _ext.code.size(); ++i)
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.insert(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
u256 nextPC = m_curPC + 1;
auto osteps = _steps;
for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1)
{
// INSTRUCTION...
Instruction inst = (Instruction)_ext.getCode(m_curPC);
// FEES...
bigint runGas = c_stepGas;
bigint newTempSize = m_temp.size();
bigint copySize = 0;
auto onOperation = [&]()
{
if (_onOp)
_onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
};
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
switch (inst)
{
case Instruction::STOP:
runGas = 0;
break;
case Instruction::SUICIDE:
require(1);
runGas = 0;
break;
case Instruction::SSTORE:
require(2);
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
runGas = 0;
_ext.sub.refunds += c_sstoreRefundGas;
}
else
runGas = c_sstoreResetGas;
break;
case Instruction::SLOAD:
require(1);
runGas = c_sloadGas;
break;
// These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE:
require(2);
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::MSTORE8:
require(2);
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
require(1);
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
require(2);
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
require(2);
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
require(3);
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
require(4);
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
case Instruction::BALANCE:
require(1);
runGas = c_balanceGas;
break;
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
require(n + 2);
runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break;
}
case Instruction::CALL:
case Instruction::CALLCODE:
require(7);
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break;
case Instruction::CREATE:
{
require(3);
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
require(2);
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
case Instruction::BLOCKHASH:
require(1);
break;
case Instruction::PC:
case Instruction::MSIZE:
case Instruction::GAS:
case Instruction::JUMPDEST:
case Instruction::ADDRESS:
case Instruction::ORIGIN:
case Instruction::CALLER:
case Instruction::CALLVALUE:
case Instruction::CALLDATASIZE:
case Instruction::CODESIZE:
case Instruction::GASPRICE:
case Instruction::COINBASE:
case Instruction::TIMESTAMP:
case Instruction::NUMBER:
case Instruction::DIFFICULTY:
case Instruction::GASLIMIT:
case Instruction::PUSH1:
case Instruction::PUSH2:
case Instruction::PUSH3:
case Instruction::PUSH4:
case Instruction::PUSH5:
case Instruction::PUSH6:
case Instruction::PUSH7:
case Instruction::PUSH8:
case Instruction::PUSH9:
case Instruction::PUSH10:
case Instruction::PUSH11:
case Instruction::PUSH12:
case Instruction::PUSH13:
case Instruction::PUSH14:
case Instruction::PUSH15:
case Instruction::PUSH16:
case Instruction::PUSH17:
case Instruction::PUSH18:
case Instruction::PUSH19:
case Instruction::PUSH20:
case Instruction::PUSH21:
case Instruction::PUSH22:
case Instruction::PUSH23:
case Instruction::PUSH24:
case Instruction::PUSH25:
case Instruction::PUSH26:
case Instruction::PUSH27:
case Instruction::PUSH28:
case Instruction::PUSH29:
case Instruction::PUSH30:
case Instruction::PUSH31:
case Instruction::PUSH32:
break;
case Instruction::NOT:
case Instruction::ISZERO:
case Instruction::CALLDATALOAD:
case Instruction::EXTCODESIZE:
case Instruction::POP:
case Instruction::JUMP:
require(1);
break;
case Instruction::ADD:
case Instruction::MUL:
case Instruction::SUB:
case Instruction::DIV:
case Instruction::SDIV:
case Instruction::MOD:
case Instruction::SMOD:
case Instruction::LT:
case Instruction::GT:
case Instruction::SLT:
case Instruction::SGT:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
case Instruction::BYTE:
case Instruction::JUMPI:
case Instruction::SIGNEXTEND:
require(2);
break;
case Instruction::ADDMOD:
case Instruction::MULMOD:
require(3);
break;
case Instruction::DUP1:
case Instruction::DUP2:
case Instruction::DUP3:
case Instruction::DUP4:
case Instruction::DUP5:
case Instruction::DUP6:
case Instruction::DUP7:
case Instruction::DUP8:
case Instruction::DUP9:
case Instruction::DUP10:
case Instruction::DUP11:
case Instruction::DUP12:
case Instruction::DUP13:
case Instruction::DUP14:
case Instruction::DUP15:
case Instruction::DUP16:
require(1 + (int)inst - (int)Instruction::DUP1);
break;
case Instruction::SWAP1:
case Instruction::SWAP2:
case Instruction::SWAP3:
case Instruction::SWAP4:
case Instruction::SWAP5:
case Instruction::SWAP6:
case Instruction::SWAP7:
case Instruction::SWAP8:
case Instruction::SWAP9:
case Instruction::SWAP10:
case Instruction::SWAP11:
case Instruction::SWAP12:
case Instruction::SWAP13:
case Instruction::SWAP14:
case Instruction::SWAP15:
case Instruction::SWAP16:
require((int)inst - (int)Instruction::SWAP1 + 2);
break;
default:
BOOST_THROW_EXCEPTION(BadInstruction());
}
newTempSize = (newTempSize + 31) / 32 * 32;
if (newTempSize > m_temp.size())
runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32;
runGas += c_copyGas * (copySize + 31) / 32;
onOperation();
// if (_onOp)
// _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
if (m_gas < runGas)
{
// Out of gas!
m_gas = 0;
BOOST_THROW_EXCEPTION(OutOfGas());
}
m_gas = (u256)((bigint)m_gas - runGas);
if (newTempSize > m_temp.size())
m_temp.resize((size_t)newTempSize);
// EXECUTE...
switch (inst)
{
case Instruction::ADD:
//pops two items and pushes S[-1] + S[-2] mod 2^256.
m_stack[m_stack.size() - 2] += m_stack.back();
m_stack.pop_back();
break;
case Instruction::MUL:
//pops two items and pushes S[-1] * S[-2] mod 2^256.
m_stack[m_stack.size() - 2] *= m_stack.back();
m_stack.pop_back();
break;
case Instruction::SUB:
m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::DIV:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() / m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back();
break;
case Instruction::SDIV:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) / u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back();
break;
case Instruction::MOD:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? m_stack.back() % m_stack[m_stack.size() - 2] : 0;
m_stack.pop_back();
break;
case Instruction::SMOD:
m_stack[m_stack.size() - 2] = m_stack[m_stack.size() - 2] ? s2u(u2s(m_stack.back()) % u2s(m_stack[m_stack.size() - 2])) : 0;
m_stack.pop_back();
break;
case Instruction::EXP:
{
auto base = m_stack.back();
auto expon = m_stack[m_stack.size() - 2];
m_stack.pop_back();
m_stack.back() = (u256)boost::multiprecision::powm((bigint)base, (bigint)expon, bigint(2) << 256);
break;
}
case Instruction::NOT:
m_stack.back() = ~m_stack.back();
break;
case Instruction::LT:
m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::GT:
m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::SLT:
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) < u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::SGT:
m_stack[m_stack.size() - 2] = u2s(m_stack.back()) > u2s(m_stack[m_stack.size() - 2]) ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::EQ:
m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0;
m_stack.pop_back();
break;
case Instruction::ISZERO:
m_stack.back() = m_stack.back() ? 0 : 1;
break;
case Instruction::AND:
m_stack[m_stack.size() - 2] = m_stack.back() & m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::OR:
m_stack[m_stack.size() - 2] = m_stack.back() | m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::XOR:
m_stack[m_stack.size() - 2] = m_stack.back() ^ m_stack[m_stack.size() - 2];
m_stack.pop_back();
break;
case Instruction::BYTE:
m_stack[m_stack.size() - 2] = m_stack.back() < 32 ? (m_stack[m_stack.size() - 2] >> (unsigned)(8 * (31 - m_stack.back()))) & 0xff : 0;
m_stack.pop_back();
break;
case Instruction::ADDMOD:
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) + bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::MULMOD:
m_stack[m_stack.size() - 3] = u256((bigint(m_stack.back()) * bigint(m_stack[m_stack.size() - 2])) % m_stack[m_stack.size() - 3]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::SIGNEXTEND:
if (m_stack.back() < 31)
{
unsigned const testBit(m_stack.back() * 8 + 7);
u256& number = m_stack[m_stack.size() - 2];
u256 mask = ((u256(1) << testBit) - 1);
if (boost::multiprecision::bit_test(number, testBit))
number |= ~mask;
else
number &= mask;
}
m_stack.pop_back();
break;
case Instruction::SHA3:
{
unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back();
m_stack.pop_back();
m_stack.push_back(sha3(bytesConstRef(m_temp.data() + inOff, inSize)));
break;
}
case Instruction::ADDRESS:
m_stack.push_back(fromAddress(_ext.myAddress));
break;
case Instruction::ORIGIN:
m_stack.push_back(fromAddress(_ext.origin));
break;
case Instruction::BALANCE:
{
m_stack.back() = _ext.balance(asAddress(m_stack.back()));
break;
}
case Instruction::CALLER:
m_stack.push_back(fromAddress(_ext.caller));
break;
case Instruction::CALLVALUE:
m_stack.push_back(_ext.value);
break;
case Instruction::CALLDATALOAD:
{
if ((unsigned)m_stack.back() + (uint64_t)31 < _ext.data.size())
m_stack.back() = (u256)*(h256 const*)(_ext.data.data() + (unsigned)m_stack.back());
else
{
h256 r;
for (uint64_t i = (unsigned)m_stack.back(), e = (unsigned)m_stack.back() + (uint64_t)32, j = 0; i < e; ++i, ++j)
r[j] = i < _ext.data.size() ? _ext.data[i] : 0;
m_stack.back() = (u256)r;
}
break;
}
case Instruction::CALLDATASIZE:
m_stack.push_back(_ext.data.size());
break;
case Instruction::CODESIZE:
m_stack.push_back(_ext.code.size());
break;
case Instruction::EXTCODESIZE:
m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size();
break;
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::EXTCODECOPY:
{
Address a;
if (inst == Instruction::EXTCODECOPY)
{
a = asAddress(m_stack.back());
m_stack.pop_back();
}
unsigned offset = (unsigned)m_stack.back();
m_stack.pop_back();
u256 index = m_stack.back();
m_stack.pop_back();
unsigned size = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned sizeToBeCopied;
switch(inst)
{
case Instruction::CALLDATACOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.data.size() ? (u256)_ext.data.size() < index ? 0 : _ext.data.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.data.data() + (unsigned)index, sizeToBeCopied);
break;
case Instruction::CODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.code.size() ? (u256)_ext.code.size() < index ? 0 : _ext.code.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.code.data() + (unsigned)index, sizeToBeCopied);
break;
case Instruction::EXTCODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < index ? 0 : _ext.codeAt(a).size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.codeAt(a).data() + (unsigned)index, sizeToBeCopied);
break;
default:
// this is unreachable, but if someone introduces a bug in the future, he may get here.
assert(false);
BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested."));
break;
}
memset(m_temp.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied);
break;
}
case Instruction::GASPRICE:
m_stack.push_back(_ext.gasPrice);
break;
case Instruction::BLOCKHASH:
m_stack.back() = (u256)_ext.blockhash(m_stack.back());
break;
case Instruction::COINBASE:
m_stack.push_back((u160)_ext.currentBlock.coinbaseAddress);
break;
case Instruction::TIMESTAMP:
m_stack.push_back(_ext.currentBlock.timestamp);
break;
case Instruction::NUMBER:
m_stack.push_back(_ext.currentBlock.number);
break;
case Instruction::DIFFICULTY:
m_stack.push_back(_ext.currentBlock.difficulty);
break;
case Instruction::GASLIMIT:
m_stack.push_back(1000000);
break;
case Instruction::PUSH1:
case Instruction::PUSH2:
case Instruction::PUSH3:
case Instruction::PUSH4:
case Instruction::PUSH5:
case Instruction::PUSH6:
case Instruction::PUSH7:
case Instruction::PUSH8:
case Instruction::PUSH9:
case Instruction::PUSH10:
case Instruction::PUSH11:
case Instruction::PUSH12:
case Instruction::PUSH13:
case Instruction::PUSH14:
case Instruction::PUSH15:
case Instruction::PUSH16:
case Instruction::PUSH17:
case Instruction::PUSH18:
case Instruction::PUSH19:
case Instruction::PUSH20:
case Instruction::PUSH21:
case Instruction::PUSH22:
case Instruction::PUSH23:
case Instruction::PUSH24:
case Instruction::PUSH25:
case Instruction::PUSH26:
case Instruction::PUSH27:
case Instruction::PUSH28:
case Instruction::PUSH29:
case Instruction::PUSH30:
case Instruction::PUSH31:
case Instruction::PUSH32:
{
int i = (int)inst - (int)Instruction::PUSH1 + 1;
nextPC = m_curPC + 1;
m_stack.push_back(0);
for (; i--; nextPC++)
m_stack.back() = (m_stack.back() << 8) | _ext.getCode(nextPC);
break;
}
case Instruction::POP:
m_stack.pop_back();
break;
case Instruction::DUP1:
case Instruction::DUP2:
case Instruction::DUP3:
case Instruction::DUP4:
case Instruction::DUP5:
case Instruction::DUP6:
case Instruction::DUP7:
case Instruction::DUP8:
case Instruction::DUP9:
case Instruction::DUP10:
case Instruction::DUP11:
case Instruction::DUP12:
case Instruction::DUP13:
case Instruction::DUP14:
case Instruction::DUP15:
case Instruction::DUP16:
{
auto n = 1 + (int)inst - (int)Instruction::DUP1;
m_stack.push_back(m_stack[m_stack.size() - n]);
break;
}
case Instruction::SWAP1:
case Instruction::SWAP2:
case Instruction::SWAP3:
case Instruction::SWAP4:
case Instruction::SWAP5:
case Instruction::SWAP6:
case Instruction::SWAP7:
case Instruction::SWAP8:
case Instruction::SWAP9:
case Instruction::SWAP10:
case Instruction::SWAP11:
case Instruction::SWAP12:
case Instruction::SWAP13:
case Instruction::SWAP14:
case Instruction::SWAP15:
case Instruction::SWAP16:
{
unsigned n = (int)inst - (int)Instruction::SWAP1 + 2;
auto d = m_stack.back();
m_stack.back() = m_stack[m_stack.size() - n];
m_stack[m_stack.size() - n] = d;
break;
}
case Instruction::MLOAD:
{
m_stack.back() = (u256)*(h256 const*)(m_temp.data() + (unsigned)m_stack.back());
break;
}
case Instruction::MSTORE:
{
*(h256*)&m_temp[(unsigned)m_stack.back()] = (h256)m_stack[m_stack.size() - 2];
m_stack.pop_back();
m_stack.pop_back();
break;
}
case Instruction::MSTORE8:
{
m_temp[(unsigned)m_stack.back()] = (byte)(m_stack[m_stack.size() - 2] & 0xff);
m_stack.pop_back();
m_stack.pop_back();
break;
}
case Instruction::SLOAD:
m_stack.back() = _ext.store(m_stack.back());
break;
case Instruction::SSTORE:
_ext.setStore(m_stack.back(), m_stack[m_stack.size() - 2]);
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::JUMP:
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
BOOST_THROW_EXCEPTION(BadJumpDestination());
m_stack.pop_back();
break;
case Instruction::JUMPI:
if (m_stack[m_stack.size() - 2])
{
nextPC = m_stack.back();
if (!m_jumpDests.count(nextPC))
BOOST_THROW_EXCEPTION(BadJumpDestination());
}
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::PC:
m_stack.push_back(m_curPC);
break;
case Instruction::MSIZE:
m_stack.push_back(m_temp.size());
break;
case Instruction::GAS:
m_stack.push_back(m_gas);
break;
case Instruction::JUMPDEST:
break;
/* case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
break;
case Instruction::LOG1:
_ext.log({m_stack[m_stack.size() - 1]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 2], (unsigned)m_stack[m_stack.size() - 3]));
break;
case Instruction::LOG2:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 3], (unsigned)m_stack[m_stack.size() - 4]));
break;
case Instruction::LOG3:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 4], (unsigned)m_stack[m_stack.size() - 5]));
break;
case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 5], (unsigned)m_stack[m_stack.size() - 6]));
break;*/
case Instruction::LOG0:
_ext.log({}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG1:
_ext.log({m_stack[m_stack.size() - 3]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG2:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG3:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::LOG4:
_ext.log({m_stack[m_stack.size() - 3], m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5], m_stack[m_stack.size() - 6]}, bytesConstRef(m_temp.data() + (unsigned)m_stack[m_stack.size() - 1], (unsigned)m_stack[m_stack.size() - 2]));
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
m_stack.pop_back();
break;
case Instruction::CREATE:
{
u256 endowment = m_stack.back();
m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned initSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024)
{
_ext.subBalance(endowment);
m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp));
}
else
m_stack.push_back(0);
break;
}
case Instruction::CALL:
case Instruction::CALLCODE:
{
u256 gas = m_stack.back();
m_stack.pop_back();
Address receiveAddress = asAddress(m_stack.back());
m_stack.pop_back();
u256 value = m_stack.back();
m_stack.pop_back();
unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned outOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned outSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024)
{
_ext.subBalance(value);
m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress));
}
else
m_stack.push_back(0);
m_gas += gas;
break;
}
case Instruction::RETURN:
{
unsigned b = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned s = (unsigned)m_stack.back();
m_stack.pop_back();
return bytesConstRef(m_temp.data() + b, s);
}
case Instruction::SUICIDE:
{
Address dest = asAddress(m_stack.back());
_ext.suicide(dest);
// ...follow through to...
}
case Instruction::STOP:
return bytesConstRef();
}
}
if (_steps == (uint64_t)-1)
BOOST_THROW_EXCEPTION(StepsDone());
return bytesConstRef();
}
}
}

4
libjsqrc/ethereumjs/.travis.yml

@ -8,4 +8,6 @@ before_script:
script:
- "jshint *.js lib"
after_script:
- npm run-script gulp
- npm run-script build
- npm test

26
libjsqrc/ethereumjs/README.md

@ -50,13 +50,35 @@ web3.eth.coinbase.then(function(result){
For another example see `example/index.html`.
## Contribute!
### Requirements
* Node.js
* npm
* gulp (build)
* mocha (tests)
```bash
sudo apt-get update
sudo apt-get install nodejs
sudo apt-get install npm
sudo apt-get install nodejs-legacy
```
## Building
* `gulp build`
```bash (gulp)
npm run-script build
```
### Testing
```bash (mocha)
npm test
```
**Please note this repo is in it's early stage.**
If you'd like to run a WebSocket ethereum node check out
@ -76,4 +98,4 @@ ethereum -ws -loglevel=4
[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
[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies

19
libjsqrc/ethereumjs/dist/ethereum.js

@ -93,6 +93,12 @@ var setupInputTypes = function () {
}
var padding = calcPadding(type, expected);
if (padding > 32)
return false; // not allowed to be so big.
padding = 32; // override as per the new ABI.
if (prefix === "string")
return web3.fromAscii(value, padding).substr(2);
if (typeof value === "number")
value = value.toString(16);
else if (typeof value === "string")
@ -111,6 +117,8 @@ var setupInputTypes = function () {
return false;
}
padding = 32; //override as per the new ABI.
return padLeft(formatter ? formatter(value) : value, padding * 2);
};
};
@ -166,12 +174,16 @@ var setupOutputTypes = function () {
}
var padding = calcPadding(type, expected);
if (padding > 32)
return -1; // not allowed to be so big.
padding = 32; // override as per the new ABI.
return padding * 2;
};
};
var namedType = function (name, padding) {
return function (type) {
padding = 32; // override as per the new ABI.
return name === type ? padding * 2 : -1;
};
};
@ -277,6 +289,7 @@ module.exports = {
methodSignature: methodSignature
};
},{}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -441,8 +454,10 @@ var contract = function (address, desc) {
transact: function (extra) {
extra = extra || {};
extra.to = address;
extra.data = parsed;
return web3.eth.transact(extra).then(onSuccess);
return abi.methodSignature(desc, method.name).then(function (signature) {
extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;
return web3.eth.transact(extra).then(onSuccess);
});
}
};
};

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

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

13
libjsqrc/ethereumjs/lib/abi.js

@ -92,6 +92,12 @@ var setupInputTypes = function () {
}
var padding = calcPadding(type, expected);
if (padding > 32)
return false; // not allowed to be so big.
padding = 32; // override as per the new ABI.
if (prefix === "string")
return web3.fromAscii(value, padding).substr(2);
if (typeof value === "number")
value = value.toString(16);
else if (typeof value === "string")
@ -110,6 +116,8 @@ var setupInputTypes = function () {
return false;
}
padding = 32; //override as per the new ABI.
return padLeft(formatter ? formatter(value) : value, padding * 2);
};
};
@ -165,12 +173,16 @@ var setupOutputTypes = function () {
}
var padding = calcPadding(type, expected);
if (padding > 32)
return -1; // not allowed to be so big.
padding = 32; // override as per the new ABI.
return padding * 2;
};
};
var namedType = function (name, padding) {
return function (type) {
padding = 32; // override as per the new ABI.
return name === type ? padding * 2 : -1;
};
};
@ -275,3 +287,4 @@ module.exports = {
outputParser: outputParser,
methodSignature: methodSignature
};

6
libjsqrc/ethereumjs/lib/contract.js

@ -57,8 +57,10 @@ var contract = function (address, desc) {
transact: function (extra) {
extra = extra || {};
extra.to = address;
extra.data = parsed;
return web3.eth.transact(extra).then(onSuccess);
return abi.methodSignature(desc, method.name).then(function (signature) {
extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;
return web3.eth.transact(extra).then(onSuccess);
});
}
};
};

6
libjsqrc/ethereumjs/package.json

@ -25,12 +25,14 @@
"jshint": ">=2.5.0",
"uglifyify": "^2.6.0",
"unreachable-branch-transform": "^0.1.0",
"vinyl-source-stream": "^1.0.0"
"vinyl-source-stream": "^1.0.0",
"mocha": ">=2.1.0"
},
"scripts": {
"build": "gulp",
"watch": "gulp watch",
"lint": "gulp lint"
"lint": "gulp lint",
"test": "mocha"
},
"repository": {
"type": "git",

37
libjsqrc/ethereumjs/test/abi.parsers.js

@ -0,0 +1,37 @@
var assert = require('assert');
var abi = require('../lib/abi.js');
describe('abi', function() {
describe('inputParser', function() {
it('should parse ...', function() {
var desc = [{
"name": "multiply",
"inputs": [
{
"name": "a",
"type": "uint256"
}
],
"outputs": [
{
"name": "d",
"type": "uint256"
}
]
}];
var iParser = abi.inputParser(desc);
assert.equal(iParser.multiply(1), "0x000000000000000000000000000000000000000000000000000000000000000001");
});
});
describe('outputParser', function() {
it('parse ...', function() {
});
});
});

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

@ -0,0 +1,18 @@
require('es6-promise').polyfill();
var assert = require('assert');
var web3 = require('../index.js');
var u = require('./utils.js');
web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider
describe('web3', function() {
describe('db', function() {
it('should have all methods implemented', function() {
u.methodExists(web3.db, 'put');
u.methodExists(web3.db, 'get');
u.methodExists(web3.db, 'putString');
u.methodExists(web3.db, 'getString');
});
});
});

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

@ -0,0 +1,42 @@
require('es6-promise').polyfill();
var assert = require('assert');
var web3 = require('../index.js');
var u = require('./utils.js');
web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider
describe('web3', function() {
describe('eth', function() {
it('should have all methods implemented', function() {
u.methodExists(web3.eth, 'balanceAt');
u.methodExists(web3.eth, 'stateAt');
u.methodExists(web3.eth, 'storageAt');
u.methodExists(web3.eth, 'countAt');
u.methodExists(web3.eth, 'codeAt');
u.methodExists(web3.eth, 'transact');
u.methodExists(web3.eth, 'call');
u.methodExists(web3.eth, 'block');
u.methodExists(web3.eth, 'transaction');
u.methodExists(web3.eth, 'uncle');
u.methodExists(web3.eth, 'compilers');
u.methodExists(web3.eth, 'lll');
u.methodExists(web3.eth, 'solidity');
u.methodExists(web3.eth, 'serpent');
u.methodExists(web3.eth, 'logs');
});
it('should have all properties implemented', function () {
u.propertyExists(web3.eth, 'coinbase');
u.propertyExists(web3.eth, 'listening');
u.propertyExists(web3.eth, 'mining');
u.propertyExists(web3.eth, 'gasPrice');
u.propertyExists(web3.eth, 'account');
u.propertyExists(web3.eth, 'accounts');
u.propertyExists(web3.eth, 'peerCount');
u.propertyExists(web3.eth, 'defaultBlock');
u.propertyExists(web3.eth, 'number');
});
});
});

2
libjsqrc/ethereumjs/test/mocha.opts

@ -0,0 +1,2 @@
--reporter Spec

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

@ -0,0 +1,19 @@
require('es6-promise').polyfill();
var assert = require('assert');
var web3 = require('../index.js');
var u = require('./utils.js');
web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider
describe('web3', function() {
describe('shh', function() {
it('should have all methods implemented', function() {
u.methodExists(web3.shh, 'post');
u.methodExists(web3.shh, 'newIdentity');
u.methodExists(web3.shh, 'haveIdentity');
u.methodExists(web3.shh, 'newGroup');
u.methodExists(web3.shh, 'addToGroup');
});
});
});

15
libjsqrc/ethereumjs/test/utils.js

@ -0,0 +1,15 @@
var assert = require('assert');
var methodExists = function (object, method) {
assert.equal('function', typeof object[method], 'method ' + method + ' is not implemented');
};
var propertyExists = function (object, property) {
assert.equal('object', typeof object[property], 'property ' + property + ' is not implemented');
};
module.exports = {
methodExists: methodExists,
propertyExists: propertyExists
};

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

@ -0,0 +1,18 @@
require('es6-promise').polyfill();
var assert = require('assert');
var web3 = require('../index.js');
var u = require('./utils.js');
web3.setProvider(new web3.providers.WebSocketProvider('http://localhost:8080')); // TODO: create some mock provider
describe('web3', function() {
it('should have all methods implemented', function() {
u.methodExists(web3, 'sha3');
u.methodExists(web3, 'toAscii');
u.methodExists(web3, 'fromAscii');
u.methodExists(web3, 'toFixed');
u.methodExists(web3, 'fromFixed');
u.methodExists(web3, 'offset');
});
});

12
libjsqrc/js.qrc

@ -1,7 +1,7 @@
<RCC version="1.0">
<qresource prefix="/js">
<file>es6-promise-2.0.0.js</file>
<file>setup.js</file>
<file alias="ethereum.js">ethereumjs/dist/ethereum.js</file>
</qresource>
<RCC>
<qresource prefix="/js">
<file>es6-promise-2.0.0.js</file>
<file>setup.js</file>
<file alias="webthree.js">ethereumjs/dist/ethereum.js</file>
</qresource>
</RCC>

2
libp2p/Host.cpp

@ -558,7 +558,7 @@ void Host::prunePeers()
for (auto i: m_peers)
if (!dc.count(i.first))
if (auto p = i.second.lock())
if (/*(m_mode != NodeMode::Host || p->m_caps != 0x01) &&*/ chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers.
if (chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers.
{
++agedPeers;
if ((!worst || p->rating() < worst->rating() || (p->rating() == worst->rating() && p->m_connect > worst->m_connect))) // kill older ones

2
libqethereum/QEthereum.h

@ -85,7 +85,7 @@ private:
_frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \
_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/ethereum.js")); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/webthree.js")); \
_frame->evaluateJavaScript(contentsOfQResource(":/js/setup.js")); \
}

1
libweb3jsonrpc/WebThreeStubServer.h

@ -51,6 +51,7 @@ private:
std::string get(std::string const& _name, std::string const& _key) override;
void put(std::string const& _name, std::string const& _key, std::string const& _value) override;
private:
dev::WebThreeDirect& m_web3;
leveldb::ReadOptions m_readOptions;

11
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -70,7 +70,7 @@ static Json::Value toJson(dev::eth::Transaction const& _t)
return res;
}
static Json::Value toJson(dev::eth::LogEntry const& _e)
static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e)
{
Json::Value res;
@ -78,13 +78,14 @@ static Json::Value toJson(dev::eth::LogEntry const& _e)
res["address"] = toJS(_e.address);
for (auto const& t: _e.topics)
res["topics"].append(toJS(t));
res["number"] = _e.number;
return res;
}
static Json::Value toJson(dev::eth::LogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7.
static Json::Value toJson(dev::eth::LocalisedLogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7.
{
Json::Value res;
for (dev::eth::LogEntry const& e: _es)
for (dev::eth::LocalisedLogEntry const& e: _es)
res.append(toJson(e));
return res;
}
@ -328,9 +329,9 @@ std::string WebThreeStubServerBase::eth_call(Json::Value const& _json)
return ret;
}
bool WebThreeStubServerBase::eth_changed(int const& _id)
Json::Value WebThreeStubServerBase::eth_changed(int const& _id)
{
return client()->checkWatch(_id);
return toJson(client()->checkWatch(_id));
}
std::string WebThreeStubServerBase::eth_codeAt(string const& _address)

2
libweb3jsonrpc/WebThreeStubServerBase.h

@ -71,7 +71,7 @@ public:
virtual Json::Value eth_blockByHash(std::string const& _hash);
virtual Json::Value eth_blockByNumber(int const& _number);
virtual std::string eth_call(Json::Value const& _json);
virtual bool eth_changed(int const& _id);
virtual Json::Value eth_changed(int const& _id);
virtual std::string eth_codeAt(std::string const& _address);
virtual std::string eth_coinbase();
virtual Json::Value eth_compilers();

4
libweb3jsonrpc/abstractwebthreestubserver.h

@ -45,7 +45,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uninstallFilterI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI);
this->bindAndAddMethod(new jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI);
this->bindAndAddMethod(new jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI);
@ -287,7 +287,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual int eth_newFilter(const Json::Value& param1) = 0;
virtual int eth_newFilterString(const std::string& param1) = 0;
virtual bool eth_uninstallFilter(const int& param1) = 0;
virtual bool eth_changed(const int& param1) = 0;
virtual Json::Value eth_changed(const int& param1) = 0;
virtual Json::Value eth_filterLogs(const int& param1) = 0;
virtual Json::Value eth_logs(const Json::Value& param1) = 0;
virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0;

2
libweb3jsonrpc/spec.json

@ -39,7 +39,7 @@
{ "name": "eth_newFilter", "params": [{}], "order": [], "returns": 0},
{ "name": "eth_newFilterString", "params": [""], "order": [], "returns": 0},
{ "name": "eth_uninstallFilter", "params": [0], "order": [], "returns": true},
{ "name": "eth_changed", "params": [0], "order": [], "returns": false},
{ "name": "eth_changed", "params": [0], "order": [], "returns": []},
{ "name": "eth_filterLogs", "params": [0], "order": [], "returns": []},
{ "name": "eth_logs", "params": [{}], "order": [], "returns": []},

12
mix/MixClient.cpp

@ -178,16 +178,16 @@ std::map<u256, u256> MixClient::storageAt(Address _a, int _block) const
return m_state.storage(_a);
}
eth::LogEntries MixClient::logs(unsigned _watchId) const
eth::LocalisedLogEntries MixClient::logs(unsigned _watchId) const
{
(void)_watchId;
return LogEntries();
return LocalisedLogEntries();
}
eth::LogEntries MixClient::logs(eth::LogFilter const& _filter) const
eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _filter) const
{
(void)_filter;
return LogEntries();
return LocalisedLogEntries();
}
unsigned MixClient::installWatch(eth::LogFilter const& _filter)
@ -208,13 +208,13 @@ void MixClient::uninstallWatch(unsigned _watchId)
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::uninstallWatch"));
}
bool MixClient::peekWatch(unsigned _watchId) const
eth::LocalisedLogEntries MixClient::peekWatch(unsigned _watchId) const
{
(void)_watchId;
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::peekWatch"));
}
bool MixClient::checkWatch(unsigned _watchId)
eth::LocalisedLogEntries MixClient::checkWatch(unsigned _watchId)
{
(void)_watchId;
BOOST_THROW_EXCEPTION(InterfaceNotSupported("dev::eth::Interface::checkWatch"));

8
mix/MixClient.h

@ -82,13 +82,13 @@ public:
u256 stateAt(Address _a, u256 _l, int _block) const override;
bytes codeAt(Address _a, int _block) const override;
std::map<u256, u256> storageAt(Address _a, int _block) const override;
eth::LogEntries logs(unsigned _watchId) const override;
eth::LogEntries logs(eth::LogFilter const& _filter) const override;
eth::LocalisedLogEntries logs(unsigned _watchId) const override;
eth::LocalisedLogEntries logs(eth::LogFilter const& _filter) const override;
unsigned installWatch(eth::LogFilter const& _filter) override;
unsigned installWatch(h256 _filterId) override;
void uninstallWatch(unsigned _watchId) override;
bool peekWatch(unsigned _watchId) const override;
bool checkWatch(unsigned _watchId) override;
eth::LocalisedLogEntries peekWatch(unsigned _watchId) const override;
eth::LocalisedLogEntries checkWatch(unsigned _watchId) override;
h256 hashFromNumber(unsigned _number) const override;
eth::BlockInfo blockInfo(h256 _hash) const override;
eth::BlockDetails blockDetails(h256 _hash) const override;

6
neth/main.cpp

@ -292,6 +292,12 @@ int nc_window_streambuf::sync()
vector<string> form_dialog(vector<string> _sfields, vector<string> _lfields, vector<string> _bfields, int _cols, int _rows, string _post_form);
enum class NodeMode
{
PeerServer,
Full
};
int main(int argc, char** argv)
{
unsigned short listenPort = 30303;

61
standard.js

@ -0,0 +1,61 @@
var compile = function(name) { return web3.eth.solidity(env.contents("../../dapp-bin/" + name + "/" + name + ".sol")); };
var create = function(code) { return web3.eth.transact({ 'code': code }); };
var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); };
var initService = function(name, dep) { return dep.then(function(){ return compile(name).then(create); }); };
var addrConfig = compile("config").then(create);
var addrNameReg = initService("namereg", addrConfig);
var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"string32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"string32"}]},{"constant":false,"inputs":[{"name":"name","type":"string32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}];
var regName = function(account, name) { return web3.contract(addrNameReg, abiNameReg).register(name).transact({'from': account, 'gas': 10000}); };
/*
var coins = initService("coins", 1, nameReg);
var coin = initService("coin", 2, coins);
var approve = function(account, approvedAddress) { web3.eth.transact({ 'from': account, 'to': coin, 'gas': '10000', 'data': [ web3.fromAscii('approve'), approvedAddress ] }); };
var exchange = initService("exchange", 3, coin);
var offer = function(account, haveCoin, haveVal, wantCoin, wantVal) { web3.eth.transact({ 'from': account, 'to': exchange, 'gas': '10000', 'data': [web3.fromAscii('new'), haveCoin, haveVal, wantCoin, wantVal] }); };
*/
addrConfig.then(function() {
env.note("config ready");
web3.eth.accounts.then(function(accounts)
{
env.note("accounts ready");
var funded = send(accounts[0], '100000000000000000000', accounts[1]);
funded.then(function(){
env.note("second account funded");
regName(accounts[1], 'Gav Would');
});
regName(accounts[0], 'Gav');
// TODO: once we have the exchange.
// approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); });
// funded.then(function(){ approve(accounts[1], exchange); });
// TODO: once we have a new implementation of DNSReg.
// env.note('Register gav.eth...')
// eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] });
});
});
// TODO
/*
var nameRegJeff;
env.note('Create NameRegJeff...')
eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; });
env.note('Register NameRegJeff...')
eth.transact({ 'to': config, 'data': ['4', nameRegJeff] });
var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00';
var dnsReg;
env.note('Create DnsReg...')
eth.transact({ 'code': dnsRegCode }, function(a) { dnsReg = a; });
env.note('DnsReg at address ' + dnsReg)
env.note('Register DnsReg...')
eth.transact({ 'to': config, 'data': ['4', dnsReg] });
*/
// env.load('/home/gav/Eth/cpp-ethereum/stdserv.js')

23
third/MainWin.cpp

@ -182,14 +182,14 @@ void Main::onKeysChanged()
installBalancesWatch();
}
unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function<void()> const& _f)
unsigned Main::installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf);
m_handlers[ret] = _f;
return ret;
}
unsigned Main::installWatch(dev::h256 _tf, std::function<void()> const& _f)
unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
{
auto ret = ethereum()->installWatch(_tf);
m_handlers[ret] = _f;
@ -198,21 +198,21 @@ unsigned Main::installWatch(dev::h256 _tf, std::function<void()> const& _f)
void Main::installWatches()
{
installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)0), [=](){ installNameRegWatch(); });
installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)1), [=](){ installCurrenciesWatch(); });
installWatch(dev::eth::ChainChangedFilter, [=](){ onNewBlock(); });
installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)0), [=](LocalisedLogEntries const&){ installNameRegWatch(); });
installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)1), [=](LocalisedLogEntries const&){ installCurrenciesWatch(); });
installWatch(dev::eth::ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
}
void Main::installNameRegWatch()
{
ethereum()->uninstallWatch(m_nameRegFilter);
m_nameRegFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); });
m_nameRegFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 0)), [=](LocalisedLogEntries const&){ onNameRegChange(); });
}
void Main::installCurrenciesWatch()
{
ethereum()->uninstallWatch(m_currenciesFilter);
m_currenciesFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); });
m_currenciesFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 1)), [=](LocalisedLogEntries const&){ onCurrenciesChange(); });
}
void Main::installBalancesWatch()
@ -228,7 +228,7 @@ void Main::installBalancesWatch()
tf.address(c).topic((u256)(u160)i.address());
ethereum()->uninstallWatch(m_balancesFilter);
m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); });
m_balancesFilter = installWatch(tf, [=](LocalisedLogEntries const&){ onBalancesChange(); });
}
void Main::onNameRegChange()
@ -536,8 +536,11 @@ void Main::timerEvent(QTimerEvent*)
m_qweb->poll();
for (auto const& i: m_handlers)
if (ethereum()->checkWatch(i.first))
i.second();
{
auto ls = ethereum()->checkWatch(i.first);
if (ls.size())
i.second(ls);
}
}
void Main::ourAccountsRowsMoved()

8
third/MainWin.h

@ -50,6 +50,8 @@ class WhisperHost;
class QQuickView;
class WebThreeStubServer;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
class Main : public QMainWindow
{
Q_OBJECT
@ -95,8 +97,8 @@ private:
void readSettings(bool _skipGeometry = false);
void writeSettings();
unsigned installWatch(dev::eth::LogFilter const& _tf, std::function<void()> const& _f);
unsigned installWatch(dev::h256 _tf, std::function<void()> const& _f);
unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f);
unsigned installWatch(dev::h256 _tf, WatchHandler const& _f);
void onNewBlock();
void onNameRegChange();
@ -124,7 +126,7 @@ private:
QList<dev::KeyPair> m_myKeys;
QList<dev::KeyPair> m_myIdentities;
std::map<unsigned, std::function<void()>> m_handlers;
std::map<unsigned, WatchHandler> m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;

Loading…
Cancel
Save