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 << "Receipt: " << toString(RLP(r)) << "
";
s << "Receipt-Hex: " << toHex(receipt.rlp()) << "
";
- s << renderDiff(ethereum()->diff(i, -1));
+ s << renderDiff(ethereum()->diff(i, 0));
// s << "Pre: " << fs.rootHash() << "
";
// s << "Post: " << ts.rootHash() << "";
}
@@ -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);
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index bb79e59ef..52a71102d 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -66,6 +66,8 @@ struct WorldState
std::vector levels;
};
+using WatchHandler = std::function;
+
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 const& _f);
- unsigned installWatch(dev::h256 _tf, std::function 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 m_webThree;
- std::map> m_handlers;
+ std::map m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;
diff --git a/eth/main.cpp b/eth/main.cpp
index a0a605193..dfe020763 100644
--- a/eth/main.cpp
+++ b/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;
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index f4803bd52..adcf70b61 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#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 l(s_x);
+ Guard l(s_x);
if (!s_seed)
{
static Nonce s_nonce;
diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp
index d73e3fa43..acd59184f 100644
--- a/libdevcrypto/CryptoPP.cpp
+++ b/libdevcrypto/CryptoPP.cpp
@@ -20,6 +20,7 @@
*/
#include "CryptoPP.h"
+#include
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 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 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 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 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 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 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 const&
bytes prefixedKey(_k.GetGroupParameters().GetEncodedElementSize(true));
{
- lock_guard 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 pk;
{
- lock_guard l(x_params);
+ Guard l(x_params);
pk.Initialize(m_params, m_params.ExponentiateBase(_e));
}
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index a57faf546..c963ee401 100644
--- a/libethereum/Client.cpp
+++ b/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 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 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 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 l(m_filterLock);
- for (pair 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& 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 l(m_filterLock);
- for (pair const& i: m_filters)
+ Guard l(m_filterLock);
+ for (pair& 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(m_bc.number(), (unsigned)_f.latest());
- unsigned end = min(begin, (unsigned)_f.earliest());
+ LocalisedLogEntries ret;
+ unsigned begin = min(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));
}
}
}
diff --git a/libethereum/Client.h b/libethereum/Client.h
index efe076dab..d0dce4cc1 100644
--- a/libethereum/Client.h
+++ b/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()
template struct ABISerialiser {};
-template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { return _t.asBytes(); } };
+template struct ABISerialiser> { static bytes serialise(FixedHash 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 { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } };
-template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } };
+template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } };
template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } };
inline bytes abiInAux() { return {}; }
@@ -125,9 +120,9 @@ template bytes abiIn(std::string _id, T const& ... _t)
}
template struct ABIDeserialiser {};
-template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret; io_t.cropped(0, N).populate(ret.ref()); return ret; } };
+template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { static_assert(N <= 32, "Parameter sizes must be at most 32 bytes."); FixedHash ret; io_t.cropped(32 - N, N).populate(ret.ref()); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } };
-template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } };
+template <> struct ABIDeserialiser { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).populate(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } };
template 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 l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } }
- virtual bool checkWatch(unsigned _watchId) { std::lock_guard 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 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 m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::vector 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?
diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp
index 0901766bf..95e1aadda 100644
--- a/libethereum/EthereumPeer.cpp
+++ b/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.
diff --git a/libethereum/Interface.h b/libethereum/Interface.h
index 28ac26819..35cd59663 100644
--- a/libethereum/Interface.h
+++ b/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;
diff --git a/libethereum/LogFilter.cpp b/libethereum/LogFilter.cpp
index 81cb439ba..eca428cfa 100644
--- a/libethereum/LogFilter.cpp
+++ b/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;
}
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index e0705859f..3c59bf415 100644
--- a/libethereum/State.cpp
+++ b/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;
diff --git a/libethereum/State.h b/libethereum/State.h
index 921c82bb9..e7e1bbfab 100644
--- a/libethereum/State.h
+++ b/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;
diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp
index b6653fe39..31c5e278a 100644
--- a/libethereum/Utility.cpp
+++ b/libethereum/Utility.cpp
@@ -23,6 +23,7 @@
#include
#include
+#include
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
diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h
index 84cfe0a94..13e8712b8 100644
--- a/libevm/ExtVMFace.h
+++ b/libevm/ExtVMFace.h
@@ -60,6 +60,16 @@ struct LogEntry
using LogEntries = std::vector;
+struct LocalisedLogEntry: public LogEntry
+{
+ LocalisedLogEntry() {}
+ LocalisedLogEntry(LogEntry const& _le, unsigned _number): LogEntry(_le), number(_number) {}
+
+ unsigned number = 0;
+};
+
+using LocalisedLogEntries = std::vector;
+
inline LogBloom bloom(LogEntries const& _logs)
{
LogBloom ret;
diff --git a/libevm/VM.cpp b/libevm/VM.cpp
index b8452e4f5..4307d9da0 100644
--- a/libevm/VM.cpp
+++ b/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(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();
+}
diff --git a/libevm/VM.h b/libevm/VM.h
index 377effe11..ecf5de292 100644
--- a/libevm/VM.h
+++ b/libevm/VM.h
@@ -77,766 +77,5 @@ private:
std::function 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(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();
-}
-
}
}
diff --git a/libjsqrc/ethereumjs/.travis.yml b/libjsqrc/ethereumjs/.travis.yml
index fafacbd5a..83b21d840 100644
--- a/libjsqrc/ethereumjs/.travis.yml
+++ b/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
+
diff --git a/libjsqrc/ethereumjs/README.md b/libjsqrc/ethereumjs/README.md
index 865b62c6b..f18d382bd 100644
--- a/libjsqrc/ethereumjs/README.md
+++ b/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
\ No newline at end of file
+[dep-dev-url]: https://david-dm.org/ethereum/ethereum.js#info=devDependencies
diff --git a/libjsqrc/ethereumjs/dist/ethereum.js b/libjsqrc/ethereumjs/dist/ethereum.js
index 26de2c02e..400a66815 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.js
+++ b/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);
+ });
}
};
};
diff --git a/libjsqrc/ethereumjs/dist/ethereum.js.map b/libjsqrc/ethereumjs/dist/ethereum.js.map
index bb29b435d..e60f94922 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.js.map
+++ b/libjsqrc/ethereumjs/dist/ethereum.js.map
@@ -12,14 +12,14 @@
"index.js"
],
"names": [],
- "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7fA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
+ "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7fA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA",
"file": "generated.js",
"sourceRoot": "",
"sourcesContent": [
"(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\nvar padLeft = function (string, chars) {\n return new Array(chars - string.length + 1).join(\"0\") + string;\n};\n\nvar calcBitPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value) / 8;\n};\n\nvar calcBytePadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value);\n};\n\nvar calcRealPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n var sizes = value.split('x');\n for (var padding = 0, i = 0; i < sizes; i++) {\n padding += (sizes[i] / 8);\n }\n return padding;\n};\n\nvar setupInputTypes = function () {\n \n var prefixedType = function (prefix, calcPadding) {\n return function (type, value) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return false;\n }\n\n var padding = calcPadding(type, expected);\n if (typeof value === \"number\")\n value = value.toString(16);\n else if (typeof value === \"string\")\n value = web3.toHex(value); \n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else\n value = (+value).toString(16);\n return padLeft(value, padding * 2);\n };\n };\n\n var namedType = function (name, padding, formatter) {\n return function (type, value) {\n if (type !== name) {\n return false;\n }\n\n return padLeft(formatter ? formatter(value) : value, padding * 2);\n };\n };\n\n var formatBool = function (value) {\n return value ? '0x1' : '0x0';\n };\n\n return [\n prefixedType('uint', calcBitPadding),\n prefixedType('int', calcBitPadding),\n prefixedType('hash', calcBitPadding),\n prefixedType('string', calcBytePadding),\n prefixedType('real', calcRealPadding),\n prefixedType('ureal', calcRealPadding),\n namedType('address', 20),\n namedType('bool', 1, formatBool),\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n\n for (var i = 0; i < method.inputs.length; i++) {\n var found = false;\n for (var j = 0; j < inputTypes.length && !found; j++) {\n found = inputTypes[j](method.inputs[i].type, params[i]);\n }\n if (!found) {\n console.error('unsupported json type: ' + method.inputs[i].type);\n }\n bytes += found;\n }\n return bytes;\n};\n\nvar setupOutputTypes = function () {\n\n var prefixedType = function (prefix, calcPadding) {\n return function (type) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return -1;\n }\n\n var padding = calcPadding(type, expected);\n return padding * 2;\n };\n };\n\n var namedType = function (name, padding) {\n return function (type) {\n return name === type ? padding * 2 : -1;\n };\n };\n\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n var formatBool = function (value) {\n return value === '1' ? true : false;\n };\n\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n return [\n { padding: prefixedType('uint', calcBitPadding), format: formatInt },\n { padding: prefixedType('int', calcBitPadding), format: formatInt },\n { padding: prefixedType('hash', calcBitPadding), format: formatHash },\n { padding: prefixedType('string', calcBytePadding), format: formatString },\n { padding: prefixedType('real', calcRealPadding), format: formatInt },\n { padding: prefixedType('ureal', calcRealPadding), format: formatInt },\n { padding: namedType('address', 20) },\n { padding: namedType('bool', 1), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n for (var i = 0; i < method.outputs.length; i++) {\n var padding = -1;\n for (var j = 0; j < outputTypes.length && padding === -1; j++) {\n padding = outputTypes[j].padding(method.outputs[i].type);\n }\n\n if (padding === -1) {\n // not found output parsing\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n",
+ "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\n// TODO: make these be actually accurate instead of falling back onto JS's doubles.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\nvar findMethodIndex = function (json, methodName) {\n return findIndex(json, function (method) {\n return method.name === methodName;\n });\n};\n\nvar padLeft = function (string, chars) {\n return new Array(chars - string.length + 1).join(\"0\") + string;\n};\n\nvar calcBitPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value) / 8;\n};\n\nvar calcBytePadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n return parseInt(value);\n};\n\nvar calcRealPadding = function (type, expected) {\n var value = type.slice(expected.length);\n if (value === \"\") {\n return 32;\n }\n var sizes = value.split('x');\n for (var padding = 0, i = 0; i < sizes; i++) {\n padding += (sizes[i] / 8);\n }\n return padding;\n};\n\nvar setupInputTypes = function () {\n \n var prefixedType = function (prefix, calcPadding) {\n return function (type, value) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return false;\n }\n\n var padding = calcPadding(type, expected);\n if (padding > 32)\n return false; // not allowed to be so big.\n padding = 32; // override as per the new ABI.\n\n if (prefix === \"string\")\n return web3.fromAscii(value, padding).substr(2);\n if (typeof value === \"number\")\n value = value.toString(16);\n else if (typeof value === \"string\")\n value = web3.toHex(value); \n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else\n value = (+value).toString(16);\n return padLeft(value, padding * 2);\n };\n };\n\n var namedType = function (name, padding, formatter) {\n return function (type, value) {\n if (type !== name) {\n return false;\n }\n\n padding = 32; //override as per the new ABI.\n\n return padLeft(formatter ? formatter(value) : value, padding * 2);\n };\n };\n\n var formatBool = function (value) {\n return value ? '0x1' : '0x0';\n };\n\n return [\n prefixedType('uint', calcBitPadding),\n prefixedType('int', calcBitPadding),\n prefixedType('hash', calcBitPadding),\n prefixedType('string', calcBytePadding),\n prefixedType('real', calcRealPadding),\n prefixedType('ureal', calcRealPadding),\n namedType('address', 20),\n namedType('bool', 1, formatBool),\n ];\n};\n\nvar inputTypes = setupInputTypes();\n\nvar toAbiInput = function (json, methodName, params) {\n var bytes = \"\";\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n var method = json[index];\n\n for (var i = 0; i < method.inputs.length; i++) {\n var found = false;\n for (var j = 0; j < inputTypes.length && !found; j++) {\n found = inputTypes[j](method.inputs[i].type, params[i]);\n }\n if (!found) {\n console.error('unsupported json type: ' + method.inputs[i].type);\n }\n bytes += found;\n }\n return bytes;\n};\n\nvar setupOutputTypes = function () {\n\n var prefixedType = function (prefix, calcPadding) {\n return function (type) {\n var expected = prefix;\n if (type.indexOf(expected) !== 0) {\n return -1;\n }\n\n var padding = calcPadding(type, expected);\n if (padding > 32)\n return -1; // not allowed to be so big.\n padding = 32; // override as per the new ABI.\n return padding * 2;\n };\n };\n\n var namedType = function (name, padding) {\n return function (type) {\n padding = 32; // override as per the new ABI.\n return name === type ? padding * 2 : -1;\n };\n };\n\n var formatInt = function (value) {\n return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value);\n };\n\n var formatHash = function (value) {\n return \"0x\" + value;\n };\n\n var formatBool = function (value) {\n return value === '1' ? true : false;\n };\n\n var formatString = function (value) {\n return web3.toAscii(value);\n };\n\n return [\n { padding: prefixedType('uint', calcBitPadding), format: formatInt },\n { padding: prefixedType('int', calcBitPadding), format: formatInt },\n { padding: prefixedType('hash', calcBitPadding), format: formatHash },\n { padding: prefixedType('string', calcBytePadding), format: formatString },\n { padding: prefixedType('real', calcRealPadding), format: formatInt },\n { padding: prefixedType('ureal', calcRealPadding), format: formatInt },\n { padding: namedType('address', 20) },\n { padding: namedType('bool', 1), format: formatBool }\n ];\n};\n\nvar outputTypes = setupOutputTypes();\n\nvar fromAbiOutput = function (json, methodName, output) {\n var index = findMethodIndex(json, methodName);\n\n if (index === -1) {\n return;\n }\n\n output = output.slice(2);\n\n var result = [];\n var method = json[index];\n for (var i = 0; i < method.outputs.length; i++) {\n var padding = -1;\n for (var j = 0; j < outputTypes.length && padding === -1; j++) {\n padding = outputTypes[j].padding(method.outputs[i].type);\n }\n\n if (padding === -1) {\n // not found output parsing\n continue;\n }\n var res = output.slice(0, padding);\n var formatter = outputTypes[j - 1].format;\n result.push(formatter ? formatter(res) : (\"0x\" + res));\n output = output.slice(padding);\n }\n\n return result;\n};\n\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n return toAbiInput(json, method.name, params);\n };\n });\n\n return parser;\n};\n\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n parser[method.name] = function (output) {\n return fromAbiOutput(json, method.name, output);\n };\n });\n\n return parser;\n};\n\nvar methodSignature = function (json, name) {\n var method = json[findMethodIndex(json, name)];\n var result = name + '(';\n var inputTypes = method.inputs.map(function (inp) {\n return inp.type;\n });\n result += inputTypes.join(',');\n result += ')';\n\n return web3.sha3(web3.fromAscii(result));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n methodSignature: methodSignature\n};\n\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file autoprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n/*\n * @brief if qt object is available, uses QtProvider,\n * if not tries to connect over websockets\n * if it fails, it uses HttpRpcProvider\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var WebSocket = require('ws'); // jshint ignore:line\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar AutoProvider = function (userOptions) {\n if (web3.haveProvider()) {\n return;\n }\n\n // before we determine what provider we are, we have to cache request\n this.sendQueue = [];\n this.onmessageQueue = [];\n\n if (navigator.qt) {\n this.provider = new web3.providers.QtProvider();\n return;\n }\n\n userOptions = userOptions || {};\n var options = {\n httprpc: userOptions.httprpc || 'http://localhost:8080',\n websockets: userOptions.websockets || 'ws://localhost:40404/eth'\n };\n\n var self = this;\n var closeWithSuccess = function (success) {\n ws.close();\n if (success) {\n self.provider = new web3.providers.WebSocketProvider(options.websockets);\n } else {\n self.provider = new web3.providers.HttpRpcProvider(options.httprpc);\n self.poll = self.provider.poll.bind(self.provider);\n }\n self.sendQueue.forEach(function (payload) {\n self.provider(payload);\n });\n self.onmessageQueue.forEach(function (handler) {\n self.provider.onmessage = handler;\n });\n };\n\n var ws = new WebSocket(options.websockets);\n\n ws.onopen = function() {\n closeWithSuccess(true);\n };\n\n ws.onerror = function() {\n closeWithSuccess(false);\n };\n};\n\nAutoProvider.prototype.send = function (payload) {\n if (this.provider) {\n this.provider.send(payload);\n return;\n }\n this.sendQueue.push(payload);\n};\n\nObject.defineProperty(AutoProvider.prototype, 'onmessage', {\n set: function (handler) {\n if (this.provider) {\n this.provider.onmessage = handler;\n return;\n }\n this.onmessageQueue.push(handler);\n }\n});\n\nmodule.exports = AutoProvider;\n",
- "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\n// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\n\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.call(extra).then(onSuccess);\n });\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n extra.data = parsed;\n return web3.eth.transact(extra).then(onSuccess);\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n",
+ "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var web3 = require('./web3'); // jshint ignore:line\n*/}\n\nvar abi = require('./abi');\n\n// method signature length in bytes\nvar ETH_METHOD_SIGNATURE_LENGTH = 4;\n\nvar contract = function (address, desc) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n var contract = {};\n\n desc.forEach(function (method) {\n contract[method.name] = function () {\n var params = Array.prototype.slice.call(arguments);\n var parsed = inputParser[method.name].apply(null, params);\n\n var onSuccess = function (result) {\n return outputParser[method.name](result);\n };\n\n return {\n call: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.call(extra).then(onSuccess);\n });\n },\n transact: function (extra) {\n extra = extra || {};\n extra.to = address;\n return abi.methodSignature(desc, method.name).then(function (signature) {\n extra.data = signature.slice(0, 2 + ETH_METHOD_SIGNATURE_LENGTH * 2) + parsed;\n return web3.eth.transact(extra).then(onSuccess);\n });\n }\n };\n };\n });\n\n return contract;\n};\n\nmodule.exports = contract;\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httprpc.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\n// TODO: is these line is supposed to be here? \nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpRpcProvider = function (host) {\n this.handlers = [];\n this.host = host;\n};\n\nfunction formatJsonRpcObject(object) {\n return {\n jsonrpc: '2.0',\n method: object.call,\n params: object.args,\n id: object._id\n };\n}\n\nfunction formatJsonRpcMessage(message) {\n var object = JSON.parse(message);\n\n return {\n _id: object.id,\n data: object.result,\n error: object.error\n };\n}\n\nHttpRpcProvider.prototype.sendRequest = function (payload, cb) {\n var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open(\"POST\", this.host, true);\n request.send(JSON.stringify(data));\n request.onreadystatechange = function () {\n if (request.readyState === 4 && cb) {\n cb(request);\n }\n };\n};\n\nHttpRpcProvider.prototype.send = function (payload) {\n var self = this;\n this.sendRequest(payload, function (request) {\n self.handlers.forEach(function (handler) {\n handler.call(self, formatJsonRpcMessage(request.responseText));\n });\n });\n};\n\nHttpRpcProvider.prototype.poll = function (payload, id) {\n var self = this;\n this.sendRequest(payload, function (request) {\n var parsed = JSON.parse(request.responseText);\n if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) {\n return;\n }\n self.handlers.forEach(function (handler) {\n handler.call(self, {_event: payload.call, _id: id, data: parsed.result});\n });\n });\n};\n\nObject.defineProperty(HttpRpcProvider.prototype, \"onmessage\", {\n set: function (handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = HttpRpcProvider;\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file qt.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * @date 2014\n */\n\nvar QtProvider = function() {\n this.handlers = [];\n\n var self = this;\n navigator.qt.onmessage = function (message) {\n self.handlers.forEach(function (handler) {\n handler.call(self, JSON.parse(message.data));\n });\n };\n};\n\nQtProvider.prototype.send = function(payload) {\n navigator.qt.postMessage(JSON.stringify(payload));\n};\n\nObject.defineProperty(QtProvider.prototype, \"onmessage\", {\n set: function(handler) {\n this.handlers.push(handler);\n }\n});\n\nmodule.exports = QtProvider;\n",
"/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file main.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\nfunction flattenPromise (obj) {\n if (obj instanceof Promise) {\n return Promise.resolve(obj);\n }\n\n if (obj instanceof Array) {\n return new Promise(function (resolve) {\n var promises = obj.map(function (o) {\n return flattenPromise(o);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < obj.length; i++) {\n obj[i] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n if (obj instanceof Object) {\n return new Promise(function (resolve) {\n var keys = Object.keys(obj);\n var promises = keys.map(function (key) {\n return flattenPromise(obj[key]);\n });\n\n return Promise.all(promises).then(function (res) {\n for (var i = 0; i < keys.length; i++) {\n obj[keys[i]] = res[i];\n }\n resolve(obj);\n });\n });\n }\n\n return Promise.resolve(obj);\n}\n\nvar web3Methods = function () {\n return [\n { name: 'sha3', call: 'web3_sha3' }\n ];\n};\n\nvar ethMethods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var methods = [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' }\n ];\n return methods;\n};\n\nvar ethProperties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'account', getter: 'eth_account' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\n ];\n};\n\nvar dbMethods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\n};\n\nvar shhMethods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\n};\n\nvar ethWatchMethods = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\nvar shhWatchMethods = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessage', call: 'shh_getMessages' }\n ];\n};\n\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n obj[method.name] = function () {\n return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) {\n var call = typeof method.call === \"function\" ? method.call(args) : method.call;\n return {call: call, args: args};\n }).then(function (request) {\n return new Promise(function (resolve, reject) {\n web3.provider.send(request, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function(err) {\n console.error(err);\n });\n };\n });\n};\n\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n var proto = {};\n proto.get = function () {\n return new Promise(function(resolve, reject) {\n web3.provider.send({call: property.getter}, function(err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n };\n if (property.setter) {\n proto.set = function (val) {\n return flattenPromise([val]).then(function (args) {\n return new Promise(function (resolve) {\n web3.provider.send({call: property.setter, args: args}, function (err, result) {\n if (!err) {\n resolve(result);\n return;\n }\n reject(err);\n });\n });\n }).catch(function (err) {\n console.error(err);\n });\n };\n }\n Object.defineProperty(obj, property.name, proto);\n });\n};\n\n// TODO: import from a dependency, don't duplicate.\nvar hexToDec = function (hex) {\n return parseInt(hex, 16).toString();\n};\n\nvar decToHex = function (dec) {\n return parseInt(dec).toString(16);\n};\n\n\nvar web3 = {\n _callbacks: {},\n _events: {},\n providers: {},\n\n toHex: function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n },\n\n toAscii: function(hex) {\n // Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x')\n i = 2;\n for(; i < l; i+=2) {\n var code = hex.charCodeAt(i);\n if(code === 0) {\n break;\n }\n\n str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));\n }\n\n return str;\n },\n\n fromAscii: function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = this.toHex(str);\n while(hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n },\n\n toDecimal: function (val) {\n return hexToDec(val.substring(2));\n },\n\n fromDecimal: function (val) {\n return \"0x\" + decToHex(val);\n },\n\n toEth: function(str) {\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ];\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n },\n\n eth: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, ethWatch);\n }\n },\n\n db: {\n prototype: Object() // jshint ignore:line\n },\n\n shh: {\n prototype: Object(), // jshint ignore:line\n watch: function (params) {\n return new Filter(params, shhWatch);\n }\n },\n\n on: function(event, id, cb) {\n if(web3._events[event] === undefined) {\n web3._events[event] = {};\n }\n\n web3._events[event][id] = cb;\n return this;\n },\n\n off: function(event, id) {\n if(web3._events[event] !== undefined) {\n delete web3._events[event][id];\n }\n\n return this;\n },\n\n trigger: function(event, id, data) {\n var callbacks = web3._events[event];\n if (!callbacks || !callbacks[id]) {\n return;\n }\n var cb = callbacks[id];\n cb(data);\n }\n};\n\nsetupMethods(web3, web3Methods());\nsetupMethods(web3.eth, ethMethods());\nsetupProperties(web3.eth, ethProperties());\nsetupMethods(web3.db, dbMethods());\nsetupMethods(web3.shh, shhMethods());\n\nvar ethWatch = {\n changed: 'eth_changed'\n};\nsetupMethods(ethWatch, ethWatchMethods());\nvar shhWatch = {\n changed: 'shh_changed'\n};\nsetupMethods(shhWatch, shhWatchMethods());\n\nvar ProviderManager = function() {\n this.queued = [];\n this.polls = [];\n this.ready = false;\n this.provider = undefined;\n this.id = 1;\n\n var self = this;\n var poll = function () {\n if (self.provider && self.provider.poll) {\n self.polls.forEach(function (data) {\n data.data._id = self.id;\n self.id++;\n self.provider.poll(data.data, data.id);\n });\n }\n setTimeout(poll, 12000);\n };\n poll();\n};\n\nProviderManager.prototype.send = function(data, cb) {\n data._id = this.id;\n if (cb) {\n web3._callbacks[data._id] = cb;\n }\n\n data.args = data.args || [];\n this.id++;\n\n if(this.provider !== undefined) {\n this.provider.send(data);\n } else {\n console.warn(\"provider is not set\");\n this.queued.push(data);\n }\n};\n\nProviderManager.prototype.set = function(provider) {\n if(this.provider !== undefined && this.provider.unload !== undefined) {\n this.provider.unload();\n }\n\n this.provider = provider;\n this.ready = true;\n};\n\nProviderManager.prototype.sendQueued = function() {\n for(var i = 0; this.queued.length; i++) {\n // Resend\n this.send(this.queued[i]);\n }\n};\n\nProviderManager.prototype.installed = function() {\n return this.provider !== undefined;\n};\n\nProviderManager.prototype.startPolling = function (data, pollId) {\n if (!this.provider || !this.provider.poll) {\n return;\n }\n this.polls.push({data: data, id: pollId});\n};\n\nProviderManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\nweb3.provider = new ProviderManager();\n\nweb3.setProvider = function(provider) {\n provider.onmessage = messageHandler;\n web3.provider.set(provider);\n web3.provider.sendQueued();\n};\n\nweb3.haveProvider = function() {\n return !!web3.provider.provider;\n};\n\nvar Filter = function(options, impl) {\n this.impl = impl;\n this.callbacks = [];\n\n var self = this;\n this.promise = impl.newFilter(options);\n this.promise.then(function (id) {\n self.id = id;\n web3.on(impl.changed, id, self.trigger.bind(self));\n web3.provider.startPolling({call: impl.changed, args: [id]}, id);\n });\n};\n\nFilter.prototype.arrived = function(callback) {\n this.changed(callback);\n};\n\nFilter.prototype.changed = function(callback) {\n var self = this;\n this.promise.then(function(id) {\n self.callbacks.push(callback);\n });\n};\n\nFilter.prototype.trigger = function(messages) {\n for(var i = 0; i < this.callbacks.length; i++) {\n this.callbacks[i].call(this, messages);\n }\n};\n\nFilter.prototype.uninstall = function() {\n var self = this;\n this.promise.then(function (id) {\n self.impl.uninstallFilter(id);\n web3.provider.stopPolling(id);\n web3.off(impl.changed, id);\n });\n};\n\nFilter.prototype.messages = function() {\n var self = this;\n return this.promise.then(function (id) {\n return self.impl.getMessages(id);\n });\n};\n\nFilter.prototype.logs = function () {\n return this.messages();\n};\n\nfunction messageHandler(data) {\n if(data._event !== undefined) {\n web3.trigger(data._event, data._id, data.data);\n return;\n }\n\n if(data._id) {\n var cb = web3._callbacks[data._id];\n if (cb) {\n cb.call(this, data.error, data.data);\n delete web3._callbacks[data._id];\n }\n }\n}\n\nif (typeof(module) !== \"undefined\")\n module.exports = web3;\n",
diff --git a/libjsqrc/ethereumjs/dist/ethereum.min.js b/libjsqrc/ethereumjs/dist/ethereum.min.js
index a0054b65e..1d909e464 100644
--- a/libjsqrc/ethereumjs/dist/ethereum.min.js
+++ b/libjsqrc/ethereumjs/dist/ethereum.min.js
@@ -1 +1 @@
-require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ai;i++)o+=r[i]/8;return o},c=function(){var t=function(t,e){return function(n,r){var o=t;if(0!==n.indexOf(o))return!1;var a=e(n,o);return r="number"==typeof r?r.toString(16):"string"==typeof r?web3.toHex(r):0===r.indexOf("0x")?r.substr(2):(+r).toString(16),i(r,2*a)}},e=function(t,e,n){return function(r,o){return r!==t?!1:i(n?n(o):o,2*e)}},n=function(t){return t?"0x1":"0x0"};return[t("uint",a),t("int",a),t("hash",a),t("string",s),t("real",u),t("ureal",u),e("address",20),e("bool",1,n)]},l=c(),h=function(t,e,n){var r="",i=o(t,e);if(-1!==i){for(var a=t[i],s=0;sn;n+=2){var o=t.charCodeAt(n);if(0===o)break;e+=String.fromCharCode(parseInt(t.substr(n,2),16))}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return p(t.substring(2))},fromDecimal:function(t){return"0x"+d(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&∋i++)o+=r[i]/8;return o},c=function(){var t=function(t,e){return function(n,r){var o=t;if(0!==n.indexOf(o))return!1;var a=e(n,o);return a>32?!1:(a=32,"string"===t?web3.fromAscii(r,a).substr(2):(r="number"==typeof r?r.toString(16):"string"==typeof r?web3.toHex(r):0===r.indexOf("0x")?r.substr(2):(+r).toString(16),i(r,2*a)))}},e=function(t,e,n){return function(r,o){return r!==t?!1:(e=32,i(n?n(o):o,2*e))}},n=function(t){return t?"0x1":"0x0"};return[t("uint",a),t("int",a),t("hash",a),t("string",s),t("real",u),t("ureal",u),e("address",20),e("bool",1,n)]},l=c(),h=function(t,e,n){var r="",i=o(t,e);if(-1!==i){for(var a=t[i],s=0;s32?-1:(o=32,2*o)}},e=function(t,e){return function(n){return e=32,t===n?2*e:-1}},r=function(t){return t.length<=8?+parseInt(t,16):n(t)},o=function(t){return"0x"+t},i=function(t){return"1"===t?!0:!1},c=function(t){return web3.toAscii(t)};return[{padding:t("uint",a),format:r},{padding:t("int",a),format:r},{padding:t("hash",a),format:o},{padding:t("string",s),format:c},{padding:t("real",u),format:r},{padding:t("ureal",u),format:r},{padding:e("address",20)},{padding:e("bool",1),format:i}]},p=f(),d=function(t,e,n){var r=o(t,e);if(-1!==r){n=n.slice(2);for(var i=[],a=t[r],s=0;sn;n+=2){var o=t.charCodeAt(n);if(0===o)break;e+=String.fromCharCode(parseInt(t.substr(n,2),16))}return e},fromAscii:function(t,e){e=void 0===e?0:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},toDecimal:function(t){return p(t.substring(2))},fromDecimal:function(t){return"0x"+d(t)},toEth:function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,n=0,r=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e>3e3&&n 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
};
+
diff --git a/libjsqrc/ethereumjs/lib/contract.js b/libjsqrc/ethereumjs/lib/contract.js
index 4cb202255..eb7fbf018 100644
--- a/libjsqrc/ethereumjs/lib/contract.js
+++ b/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);
+ });
}
};
};
diff --git a/libjsqrc/ethereumjs/package.json b/libjsqrc/ethereumjs/package.json
index fc34be487..b4f180d10 100644
--- a/libjsqrc/ethereumjs/package.json
+++ b/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",
diff --git a/libjsqrc/ethereumjs/test/abi.parsers.js b/libjsqrc/ethereumjs/test/abi.parsers.js
new file mode 100644
index 000000000..06a77fb86
--- /dev/null
+++ b/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() {
+
+ });
+ });
+});
+
diff --git a/libjsqrc/ethereumjs/test/db.methods.js b/libjsqrc/ethereumjs/test/db.methods.js
new file mode 100644
index 000000000..b4abfc4d7
--- /dev/null
+++ b/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');
+ });
+ });
+});
+
diff --git a/libjsqrc/ethereumjs/test/eth.methods.js b/libjsqrc/ethereumjs/test/eth.methods.js
new file mode 100644
index 000000000..7190b27d2
--- /dev/null
+++ b/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');
+ });
+ });
+});
+
+
diff --git a/libjsqrc/ethereumjs/test/mocha.opts b/libjsqrc/ethereumjs/test/mocha.opts
new file mode 100644
index 000000000..b2db8d5a7
--- /dev/null
+++ b/libjsqrc/ethereumjs/test/mocha.opts
@@ -0,0 +1,2 @@
+--reporter Spec
+
diff --git a/libjsqrc/ethereumjs/test/shh.methods.js b/libjsqrc/ethereumjs/test/shh.methods.js
new file mode 100644
index 000000000..08f573a3c
--- /dev/null
+++ b/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');
+ });
+ });
+});
+
diff --git a/libjsqrc/ethereumjs/test/utils.js b/libjsqrc/ethereumjs/test/utils.js
new file mode 100644
index 000000000..4c508da67
--- /dev/null
+++ b/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
+};
+
diff --git a/libjsqrc/ethereumjs/test/web3.methods.js b/libjsqrc/ethereumjs/test/web3.methods.js
new file mode 100644
index 000000000..a7e020978
--- /dev/null
+++ b/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');
+ });
+});
+
diff --git a/libjsqrc/js.qrc b/libjsqrc/js.qrc
index eee8f6652..896ab472f 100644
--- a/libjsqrc/js.qrc
+++ b/libjsqrc/js.qrc
@@ -1,7 +1,7 @@
-
-
- es6-promise-2.0.0.js
- setup.js
- ethereumjs/dist/ethereum.js
-
+
+
+ es6-promise-2.0.0.js
+ setup.js
+ ethereumjs/dist/ethereum.js
+
diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp
index d1c3cd19b..4be6f228f 100644
--- a/libp2p/Host.cpp
+++ b/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
diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h
index 657986b36..49df0f703 100644
--- a/libqethereum/QEthereum.h
+++ b/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")); \
}
diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h
index b76fc17e9..d401c38fc 100644
--- a/libweb3jsonrpc/WebThreeStubServer.h
+++ b/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;
diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp
index 565db9555..5003454f0 100644
--- a/libweb3jsonrpc/WebThreeStubServerBase.cpp
+++ b/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)
diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h
index 6868207a6..168ab288a 100644
--- a/libweb3jsonrpc/WebThreeStubServerBase.h
+++ b/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();
diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h
index 779d8bec3..15c53e0fa 100644
--- a/libweb3jsonrpc/abstractwebthreestubserver.h
+++ b/libweb3jsonrpc/abstractwebthreestubserver.h
@@ -45,7 +45,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(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 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"));
diff --git a/mix/MixClient.h b/mix/MixClient.h
index 4cbaad6e8..b7ba7fbf3 100644
--- a/mix/MixClient.h
+++ b/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 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;
diff --git a/neth/main.cpp b/neth/main.cpp
index 0b48edc11..1252b205b 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -292,6 +292,12 @@ int nc_window_streambuf::sync()
vector form_dialog(vector _sfields, vector _lfields, vector _bfields, int _cols, int _rows, string _post_form);
+enum class NodeMode
+{
+ PeerServer,
+ Full
+};
+
int main(int argc, char** argv)
{
unsigned short listenPort = 30303;
diff --git a/standard.js b/standard.js
new file mode 100644
index 000000000..74ebc74ad
--- /dev/null
+++ b/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')
diff --git a/third/MainWin.cpp b/third/MainWin.cpp
index 894f1af0f..2e967e407 100644
--- a/third/MainWin.cpp
+++ b/third/MainWin.cpp
@@ -182,14 +182,14 @@ void Main::onKeysChanged()
installBalancesWatch();
}
-unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function 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 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 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()
diff --git a/third/MainWin.h b/third/MainWin.h
index 478fb6fb6..3b4acc3a8 100644
--- a/third/MainWin.h
+++ b/third/MainWin.h
@@ -50,6 +50,8 @@ class WhisperHost;
class QQuickView;
class WebThreeStubServer;
+using WatchHandler = std::function;
+
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 const& _f);
- unsigned installWatch(dev::h256 _tf, std::function 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 m_myKeys;
QList m_myIdentities;
- std::map> m_handlers;
+ std::map m_handlers;
unsigned m_nameRegFilter = (unsigned)-1;
unsigned m_currenciesFilter = (unsigned)-1;
unsigned m_balancesFilter = (unsigned)-1;