Browse Source

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

cl-refactor
Paweł Bylica 10 years ago
parent
commit
c943ea3076
  1. 18
      CodingStandards.txt
  2. 2
      README.md
  3. 8
      alethzero/MainWin.cpp
  4. 1
      alethzero/MainWin.h
  5. 6
      eth/main.cpp
  6. 15
      exp/main.cpp
  7. 2
      libdevcore/Common.cpp
  8. 2
      libdevcore/Exceptions.h
  9. 1
      libdevcore/Worker.cpp
  10. 1
      libdevcore/Worker.h
  11. 5
      libdevcrypto/Common.cpp
  12. 2
      libdevcrypto/CryptoHeaders.h
  13. 4
      libdevcrypto/MemoryDB.cpp
  14. 3
      libdevcrypto/MemoryDB.h
  15. 4
      libdevcrypto/OverlayDB.cpp
  16. 3
      libdevcrypto/OverlayDB.h
  17. 4
      libdevcrypto/SHA3.cpp
  18. 3
      libdevcrypto/SHA3.h
  19. 3
      libdevcrypto/TrieCommon.cpp
  20. 22
      libdevcrypto/TrieCommon.h
  21. 3
      libdevcrypto/TrieDB.cpp
  22. 164
      libdevcrypto/TrieDB.h
  23. 2
      libethcore/BlockInfo.cpp
  24. 2
      libethcore/CommonEth.cpp
  25. 16
      libethcore/Exceptions.h
  26. 4
      libethereum/BlockChain.h
  27. 15
      libethereum/Client.cpp
  28. 5
      libethereum/CommonNet.h
  29. 5
      libethereum/EthereumHost.cpp
  30. 3
      libethereum/EthereumPeer.cpp
  31. 2
      libethereum/MessageFilter.cpp
  32. 15
      libethereum/State.cpp
  33. 3
      libethereum/State.h
  34. 2
      libethereum/Transaction.cpp
  35. 4
      libethereum/Transaction.h
  36. 2
      libevm/VM.h
  37. 2
      libp2p/Common.h
  38. 125
      libp2p/Host.cpp
  39. 13
      libp2p/Host.h
  40. 4
      libp2p/Session.cpp
  41. 2
      libp2p/UPnP.h
  42. 111
      libqethereum/QEthereum.cpp
  43. 90
      libqethereum/QEthereum.h
  44. 22
      libwebthree/WebThree.cpp
  45. 6
      libwebthree/WebThree.h
  46. 2
      libwhisper/Common.h
  47. 11
      libwhisper/Interface.cpp
  48. 19
      libwhisper/Interface.h
  49. 8
      libwhisper/Message.h
  50. 2
      libwhisper/WhisperHost.h
  51. 2
      neth/main.cpp
  52. 39
      qtcreator-style.xml
  53. 7
      test/CMakeLists.txt
  54. 4
      test/MemTrie.cpp
  55. 11
      test/TestHelperCrypto.h
  56. 152
      test/createRandomTest.cpp
  57. 2
      test/crypto.cpp
  58. 1
      test/hexPrefix.cpp
  59. 29
      test/randomTestFiller.json
  60. 2
      test/rlp.cpp
  61. 46
      test/trie.cpp
  62. 74
      test/vm.cpp
  63. 85
      test/vmArithmeticTestFiller.json
  64. 83
      test/vmIOandFlowOperationsTestFiller.json
  65. 100
      test/vmSystemOperationsTestFiller.json
  66. 4
      third/MainWin.cpp
  67. 1
      third/MainWin.h

18
CodingStandards.txt

@ -1,7 +1,7 @@
0. Formatting
a. Use tabs for indentation!
- 1 tab is 4 spaces wide.
- tab stops are every 4 characters.
- One indentation level -> exactly one byte (i.e. a tab character) in the source file.
b. Line widths:
- Don't worry about having lines of code > 80-char wide.
@ -11,8 +11,9 @@ d. Never place condition bodies on same line as condition.
e. Space between first paren and keyword, but *not* following first paren or preceeding final paren.
f. No spaces when fewer than intra-expression three parens together; when three or more, space according to clarity.
g. No spaces for subscripting.
h. Space all other operators.
i. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
h. No space before ':' but one after it, except in the ternary operator: one on both sides.
i. Space all other operators.
j. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
(WRONG)
if( a==b[ i ] ) { printf ("Hello\n"); }
@ -147,8 +148,17 @@ e. A dictionary and thesaurus are your friends.
- Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
10. Type-definitions
10. Commenting
a. Prefer using to typedef. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;
b. Generally avoid shortening a standard form that already includes all important information:
- e.g. stick to shared_ptr<X> rather than shortening to ptr<X>.
c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
- e.g. using Guard = boost::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it's clear in meaning and used commonly.
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation.

2
README.md

@ -6,6 +6,8 @@ By Gav Wood, 2014.
+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) master [![Build
+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) develop
[![Stories in Ready](https://badge.waffle.io/ethereum/cpp-ethereum.png?label=ready&title=Ready)](http://waffle.io/ethereum/cpp-ethereum)
Ethereum is based on a design in an original whitepaper by Vitalik Buterin. This implementation is based on the formal specification of a refinement of that idea detailed in the 'yellow paper' by Gavin Wood. Contributors, builders and testers include Alex Leverington (Clang & Mac building, client multiplexing), Tim Hughes (MSVC compilation & Dagger testing), Caktux (ongoing CI), Christoph Jentzsch (tests), Christian Reissweiner (Solidity), Marek Kotewicz (external JS & JSON-RPC), Eric Lombrozo (MinGW32 cross-compilation), Marko Simovic (original CI), and several others.
### Building

8
alethzero/MainWin.cpp

@ -135,15 +135,17 @@ Main::Main(QWidget *parent) :
connect(ui->webView, &QWebView::loadStarted, [this]()
{
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_dev = new QDev(this);
m_ethereum = new QEthereum(this, ethereum(), owned());
m_whisper = new QWhisper(this, whisper());
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
auto qdev = m_dev;
auto qeth = m_ethereum;
auto qshh = m_whisper;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, qeth, qshh, this));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh));
});
connect(ui->webView, &QWebView::loadFinished, [=]()
@ -1327,7 +1329,7 @@ void Main::on_contracts_currentItemChanged()
s << "<h4>Body Code</h4>" << disassemble(ethereum()->codeAt(address));
ui->contractInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::eth::InvalidTrie)
catch (dev::InvalidTrie)
{
ui->contractInfo->appendHtml("Corrupted trie.");
}
@ -1864,7 +1866,7 @@ QString Main::prettyU256(dev::u256 _n) const
s << "<span style=\"color: #008\">" << (uint64_t)_n << "</span> <span style=\"color: #448\">(0x" << hex << (uint64_t)_n << ")</span>";
else if (!~(_n >> 64))
s << "<span style=\"color: #008\">" << (int64_t)_n << "</span> <span style=\"color: #448\">(0x" << hex << (int64_t)_n << ")</span>";
else if ((_n >> 200) == 0)
else if ((_n >> 160) == 0)
{
Address a = right160(_n);
QString n = pretty(a);

1
alethzero/MainWin.h

@ -247,6 +247,7 @@ private:
QString m_logHistory;
bool m_logChanged = true;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr;
};

6
eth/main.cpp

@ -324,7 +324,7 @@ int main(int argc, char** argv)
c->setAddress(coinbase);
}
auto nodesState = contents(dbPath + "/nodeState.rlp");
auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/nodeState.rlp");
web3.restoreNodes(&nodesState);
cout << "Address: " << endl << toHex(us.address().asArray()) << endl;
@ -700,7 +700,7 @@ int main(int argc, char** argv)
cnote << "Saved" << rechex << "to" << outFile;
}
catch (dev::eth::InvalidTrie)
catch (dev::InvalidTrie)
{
cwarn << "Corrupted trie.";
}
@ -791,7 +791,7 @@ int main(int argc, char** argv)
while (!g_exit)
this_thread::sleep_for(chrono::milliseconds(1000));
writeFile(dbPath + "/nodeState.rlp", web3.saveNodes());
writeFile((dbPath.size() ? dbPath : getDataDir()) + "/nodeState.rlp", web3.saveNodes());
return 0;
}

15
exp/main.cpp

@ -29,12 +29,14 @@
#include <libdevcore/RangeMask.h>
#include <libethereum/DownloadMan.h>
#include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace dev::p2p;
using namespace dev::shh;
#if 0
int main()
{
DownloadMan man;
@ -69,8 +71,8 @@ int main()
cnote << i;*/
return 0;
}
#endif
/*
int main(int argc, char** argv)
{
g_logVerbosity = 20;
@ -102,15 +104,16 @@ int main(int argc, char** argv)
ph.connect(remoteHost, remotePort);
/// Only interested in the packet if the lowest bit is 1
auto w = wh->installWatch(MessageFilter(std::vector<std::pair<bytes, bytes> >({{fromHex("0000000000000000000000000000000000000000000000000000000000000001"), fromHex("0000000000000000000000000000000000000000000000000000000000000001")}})));
auto w = wh->installWatch(MessageFilter(TopicMasks({{Topic("0000000000000000000000000000000000000000000000000000000000000001"), Topic("0000000000000000000000000000000000000000000000000000000000000001")}})));
for (int i = 0; ; ++i)
{
wh->sendRaw(h256(u256(i * i)).asBytes(), h256(u256(i)).asBytes(), 1000);
wh->sendRaw(RLPStream().append(i * i).out(), Topic(u256(i)), 1000);
for (auto i: wh->checkWatch(w))
cnote << "New message:" << (u256)h256(wh->message(i).payload);
{
auto p = wh->message(i).payload;
cnote << "New message:" << RLP(p).toInt<unsigned>();
}
}
return 0;
}
*/

2
libdevcore/Common.cpp

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

2
libdevcore/Exceptions.h

@ -44,6 +44,6 @@ struct FileError: virtual Exception {};
// error information to be added to exceptions
typedef boost::error_info<struct tag_invalidSymbol, char> errinfo_invalidSymbol;
typedef boost::error_info<struct tag_comment, Address> errinfo_wrongAddress;
typedef boost::error_info<struct tag_comment, std::string> errinfo_wrongAddress;
typedef boost::error_info<struct tag_comment, std::string> errinfo_comment;
}

1
libdevcore/Worker.cpp

@ -38,6 +38,7 @@ void Worker::startWorking()
m_work.reset(new thread([&]()
{
setThreadName(m_name.c_str());
startedWorking();
while (!m_stop)
{
this_thread::sleep_for(chrono::milliseconds(30));

1
libdevcore/Worker.h

@ -46,6 +46,7 @@ protected:
void startWorking();
void stopWorking();
bool isWorking() const { Guard l(x_work); return !!m_work; }
virtual void startedWorking() {}
virtual void doWork() = 0;
virtual void doneWorking() {}

5
libdevcrypto/Common.cpp

@ -25,7 +25,6 @@
#include "SHA3.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
//#define ETH_ADDRESS_DEBUG 1
@ -46,7 +45,7 @@ Address dev::toAddress(Secret _private)
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return Address();
auto ret = right160(dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << _private << endl;
@ -94,7 +93,7 @@ KeyPair::KeyPair(h256 _sec):
m_secret = m_secret;
memcpy(m_public.data(), &(pubkey[1]), 64);
m_address = right160(dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
m_address = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;

2
libdevcrypto/CryptoHeaders.h

@ -29,6 +29,8 @@
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <sha.h>
#include <sha3.h>
#include <ripemd.h>

4
libdevcrypto/MemoryDB.cpp

@ -23,12 +23,9 @@
#include "MemoryDB.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace dev
{
namespace eth
{
std::map<h256, std::string> MemoryDB::get() const
{
@ -116,4 +113,3 @@ set<h256> MemoryDB::keys() const
}
}
}

3
libdevcrypto/MemoryDB.h

@ -29,8 +29,6 @@
namespace dev
{
namespace eth
{
struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 18; };
@ -85,4 +83,3 @@ inline std::ostream& operator<<(std::ostream& _out, MemoryDB const& _m)
}
}
}

4
libdevcrypto/OverlayDB.cpp

@ -23,12 +23,9 @@
#include "OverlayDB.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace dev
{
namespace eth
{
OverlayDB::~OverlayDB()
{
@ -100,4 +97,3 @@ void OverlayDB::kill(h256 _h)
}
}
}

3
libdevcrypto/OverlayDB.h

@ -34,8 +34,6 @@ namespace ldb = leveldb;
namespace dev
{
namespace eth
{
class OverlayDB: public MemoryDB
{
@ -63,4 +61,3 @@ private:
};
}
}

4
libdevcrypto/SHA3.cpp

@ -24,12 +24,9 @@
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace dev
{
namespace eth
{
h256 EmptySHA3 = sha3(bytesConstRef());
@ -118,4 +115,3 @@ bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned
}
}
}

3
libdevcrypto/SHA3.h

@ -29,8 +29,6 @@
namespace dev
{
namespace eth
{
// SHA-3 convenience routines.
@ -69,4 +67,3 @@ void sha256(bytesConstRef _input, bytesRef _output);
void ripemd160(bytesConstRef _input, bytesRef _output);
}
}

3
libdevcrypto/TrieCommon.cpp

@ -23,8 +23,6 @@
namespace dev
{
namespace eth
{
/*
* Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1
@ -127,4 +125,3 @@ byte uniqueInUse(RLP const& _orig, byte except)
}
}
}

22
libdevcrypto/TrieCommon.h

@ -26,8 +26,6 @@
namespace dev
{
namespace eth
{
inline byte nibble(bytesConstRef _data, unsigned _i)
{
@ -49,10 +47,29 @@ struct NibbleSlice
NibbleSlice(bytesConstRef _d = bytesConstRef(), unsigned _o = 0): data(_d), offset(_o) {}
byte operator[](unsigned _index) const { return nibble(data, offset + _index); }
unsigned size() const { return data.size() * 2 - offset; }
bool empty() const { return !size(); }
NibbleSlice mid(unsigned _index) const { return NibbleSlice(data, offset + _index); }
void clear() { data.reset(); offset = 0; }
bool contains(NibbleSlice _k) const { return shared(_k) == _k.size(); }
unsigned shared(NibbleSlice _k) const { return sharedNibbles(data, offset, offset + size(), _k.data, _k.offset, _k.offset + _k.size()); }
/**
* @brief Determine if we, a full key, are situated prior to a particular key-prefix.
* @param _k The prefix.
* @return true if we are strictly prior to the prefix.
*/
bool isEarlierThan(NibbleSlice _k) const
{
unsigned i;
for (i = 0; i < _k.size() && i < size(); ++i)
if (operator[](i) < _k[i]) // Byte is lower - we're earlier..
return true;
else if (operator[](i) > _k[i]) // Byte is higher - we're not earlier.
return false;
if (i >= _k.size()) // Ran past the end of the prefix - we're == for the entire prefix - we're not earlier.
return false;
return true; // Ran out before the prefix had finished - we're earlier.
}
bool operator==(NibbleSlice _k) const { return _k.size() == size() && shared(_k) == _k.size(); }
bool operator!=(NibbleSlice _s) const { return !operator==(_s); }
};
@ -102,4 +119,3 @@ inline std::string hexPrefixEncode(NibbleSlice _s1, NibbleSlice _s2, bool _leaf)
}
}
}

3
libdevcrypto/TrieDB.cpp

@ -23,10 +23,9 @@
#include "TrieDB.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
#if !ETH_LANGUAGES
const h256 dev::eth::c_shaNull = sha3(rlp(""));
const h256 dev::c_shaNull = sha3(rlp(""));
#endif

164
libdevcrypto/TrieDB.h

@ -39,8 +39,6 @@ namespace ldb = leveldb;
namespace dev
{
namespace eth
{
struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 17; };
#define tdebug clog(TrieDBChannel)
@ -171,6 +169,7 @@ public:
iterator() {}
iterator(GenericTrieDB const* _db);
iterator(GenericTrieDB const* _db, bytesConstRef _key);
iterator& operator++() { next(); return *this; }
@ -184,13 +183,17 @@ public:
private:
void next();
void next(NibbleSlice _key);
struct Node
{
std::string rlp;
std::string key; // as hexPrefixEncoding.
byte child; // 255 -> entering
byte child; // 255 -> entering, 16 -> actually at the node, 17 -> exiting, 0-15 -> actual children.
// 255 -> 16 -> 0 -> 1 -> ... -> 15 -> 17
void setChild(unsigned _i) { child = _i; }
void setFirstChild() { child = 16; }
void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); }
@ -205,6 +208,8 @@ public:
iterator begin() const { return this; }
iterator end() const { return iterator(); }
iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); }
private:
RLPStream& streamNode(RLPStream& _s, bytes const& _b);
@ -298,6 +303,7 @@ public:
iterator() {}
iterator(TrieDB const* _db): Super(_db) {}
iterator(TrieDB const* _db, bytesConstRef _k): Super(_db, _k) {}
value_type operator*() const { return at(); }
value_type operator->() const { return at(); }
@ -307,6 +313,7 @@ public:
iterator begin() const { return this; }
iterator end() const { return iterator(); }
iterator lower_bound(KeyType _k) const { return iterator(this, bytesConstRef((byte const*)&_k, sizeof(KeyType))); }
};
template <class KeyType, class DB>
@ -317,14 +324,11 @@ std::ostream& operator<<(std::ostream& _out, TrieDB<KeyType, DB> const& _db)
return _out;
}
}
}
// Template implementations...
namespace dev
{
namespace eth
{
template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _db)
{
@ -333,6 +337,13 @@ template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _
next();
}
template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _db, bytesConstRef _fullKey)
{
m_that = _db;
m_trail.push_back({_db->node(_db->m_root), std::string(1, '\0'), 255}); // one null byte is the HPE for the empty key.
next(_fullKey);
}
template <class DB> typename GenericTrieDB<DB>::iterator::value_type GenericTrieDB<DB>::iterator::at() const
{
assert(m_trail.size());
@ -341,10 +352,145 @@ template <class DB> typename GenericTrieDB<DB>::iterator::value_type GenericTrie
assert(!(b.key[0] & 0x10)); // should be an integer number of bytes (i.e. not an odd number of nibbles).
RLP rlp(b.rlp);
return std::make_pair(bytesConstRef(b.key).cropped(1), rlp[rlp.itemCount() == 2 ? 1 : 16].payload());
}
template <class DB> void GenericTrieDB<DB>::iterator::next(NibbleSlice _key)
{
NibbleSlice k = _key;
while (true)
{
if (m_trail.empty())
{
m_that = nullptr;
return;
}
Node const& b = m_trail.back();
RLP rlp(b.rlp);
if (m_trail.back().child == 255)
{
// Entering. Look for first...
if (rlp.isEmpty())
{
// Kill our search as soon as we hit an empty node.
k.clear();
m_trail.pop_back();
continue;
}
if (!rlp.isList() || (rlp.itemCount() != 2 && rlp.itemCount() != 17))
{
#if ETH_PARANOIA
cwarn << "BIG FAT ERROR. STATE TRIE CORRUPTED!!!!!";
cwarn << b.rlp.size() << toHex(b.rlp);
cwarn << rlp;
auto c = rlp.itemCount();
cwarn << c;
BOOST_THROW_EXCEPTION(InvalidTrie());
#else
m_that = nullptr;
return;
#endif
}
if (rlp.itemCount() == 2)
return std::make_pair(bytesConstRef(b.key).cropped(1), rlp[1].payload());
{
// Just turn it into a valid Branch
auto keyOfRLP = keyOf(rlp);
// TODO: do something different depending on how keyOfRLP compares to k.mid(0, std::min(k.size(), keyOfRLP.size()));
// if == all is good - continue descent.
// if > discard key and continue descent.
// if < discard key and skip node.
if (!k.contains(keyOfRLP))
{
if (!k.isEarlierThan(keyOfRLP))
{
k.clear();
m_trail.pop_back();
continue;
}
k.clear();
}
k = k.mid(std::min(k.size(), keyOfRLP.size()));
m_trail.back().key = hexPrefixEncode(keyOf(m_trail.back().key), keyOfRLP, false);
if (isLeaf(rlp))
{
// leaf - exit now.
if (k.empty())
{
m_trail.back().child = 0;
return;
}
// Still data in key we're supposed to be looking for when we're at a leaf. Go for next one.
k.clear();
m_trail.pop_back();
continue;
}
// enter child.
m_trail.back().rlp = m_that->deref(rlp[1]);
// no need to set .child as 255 - it's already done.
continue;
}
else
return std::make_pair(bytesConstRef(b.key).cropped(1), rlp[16].payload());
{
// Already a branch - look for first valid.
if (k.size())
{
m_trail.back().setChild(k[0]);
k = k.mid(1);
}
else
m_trail.back().setChild(16);
// run through to...
}
}
else
{
// Continuing/exiting. Look for next...
if (!(rlp.isList() && rlp.itemCount() == 17))
{
k.clear();
m_trail.pop_back();
continue;
}
// else run through to...
m_trail.back().incrementChild();
}
// ...here. should only get here if we're a list.
assert(rlp.isList() && rlp.itemCount() == 17);
for (;; m_trail.back().incrementChild())
if (m_trail.back().child == 17)
{
// finished here.
k.clear();
m_trail.pop_back();
break;
}
else if (!rlp[m_trail.back().child].isEmpty())
{
if (m_trail.back().child == 16)
return; // have a value at this node - exit now.
else
{
// lead-on to another node - enter child.
// fixed so that Node passed into push_back is constructed *before* m_trail is potentially resized (which invalidates back and rlp)
Node const& back = m_trail.back();
m_trail.push_back(Node{
m_that->deref(rlp[back.child]),
hexPrefixEncode(keyOf(back.key), NibbleSlice(bytesConstRef(&back.child, 1), 1), false),
255
});
break;
}
}
else
k.clear();
}
}
template <class DB> void GenericTrieDB<DB>::iterator::next()
@ -923,5 +1069,3 @@ template <class DB> bytes GenericTrieDB<DB>::branch(RLP const& _orig)
}
}
}

2
libethcore/BlockInfo.cpp

@ -72,7 +72,7 @@ h256 BlockInfo::headerHash(bytesConstRef _block)
void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{
hash = dev::eth::sha3(_header.data());
hash = dev::sha3(_header.data());
int field = 0;
try

2
libethcore/CommonEth.cpp

@ -100,7 +100,7 @@ Address toAddress(Secret _private)
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return Address();
auto ret = right160(dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
auto ret = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << _private << endl;

16
libethcore/Exceptions.h

@ -44,26 +44,26 @@ struct FeeTooSmall: virtual dev::Exception {};
struct TooMuchGasUsed: virtual dev::Exception {};
struct ExtraDataTooBig: virtual dev::Exception {};
struct InvalidSignature: virtual dev::Exception {};
class InvalidBlockFormat: public dev::Exception { public: InvalidBlockFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual const char* what() const noexcept; };
class InvalidBlockFormat: virtual public dev::Exception { public: InvalidBlockFormat(int _f, bytesConstRef _d): m_f(_f), m_d(_d.toBytes()) {} int m_f; bytes m_d; virtual const char* what() const noexcept; };
struct InvalidUnclesHash: virtual dev::Exception {};
struct InvalidUncle: virtual dev::Exception {};
struct UncleTooOld: virtual dev::Exception {};
class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual const char* what() const noexcept; };
class UncleInChain: virtual public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual const char* what() const noexcept; };
struct DuplicateUncleNonce: virtual dev::Exception {};
struct InvalidStateRoot: virtual dev::Exception {};
class InvalidTransactionsHash: public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual const char* what() const noexcept; };
class InvalidTransactionsHash: virtual public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual const char* what() const noexcept; };
struct InvalidTransaction: virtual dev::Exception {};
struct InvalidDifficulty: virtual dev::Exception {};
class InvalidGasLimit: public dev::Exception { public: InvalidGasLimit(u256 _provided = 0, u256 _valid = 0): provided(_provided), valid(_valid) {} u256 provided; u256 valid; virtual const char* what() const noexcept; };
class InvalidMinGasPrice: public dev::Exception { public: InvalidMinGasPrice(u256 _provided = 0, u256 _limit = 0): provided(_provided), limit(_limit) {} u256 provided; u256 limit; virtual const char* what() const noexcept; };
class InvalidGasLimit: virtual public dev::Exception { public: InvalidGasLimit(u256 _provided = 0, u256 _valid = 0): provided(_provided), valid(_valid) {} u256 provided; u256 valid; virtual const char* what() const noexcept; };
class InvalidMinGasPrice: virtual public dev::Exception { public: InvalidMinGasPrice(u256 _provided = 0, u256 _limit = 0): provided(_provided), limit(_limit) {} u256 provided; u256 limit; virtual const char* what() const noexcept; };
struct InvalidTransactionGasUsed: virtual dev::Exception {};
struct InvalidTransactionStateRoot: virtual dev::Exception {};
struct InvalidTimestamp: virtual dev::Exception {};
class InvalidNonce: public dev::Exception { public: InvalidNonce(u256 _required = 0, u256 _candidate = 0): required(_required), candidate(_candidate) {} u256 required; u256 candidate; virtual const char* what() const noexcept; };
class InvalidBlockNonce: public dev::Exception { public: InvalidBlockNonce(h256 _h = h256(), h256 _n = h256(), u256 _d = 0): h(_h), n(_n), d(_d) {} h256 h; h256 n; u256 d; virtual const char* what() const noexcept; };
class InvalidNonce: virtual public dev::Exception { public: InvalidNonce(u256 _required = 0, u256 _candidate = 0): required(_required), candidate(_candidate) {} u256 required; u256 candidate; virtual const char* what() const noexcept; };
class InvalidBlockNonce: virtual public dev::Exception { public: InvalidBlockNonce(h256 _h = h256(), h256 _n = h256(), u256 _d = 0): h(_h), n(_n), d(_d) {} h256 h; h256 n; u256 d; virtual const char* what() const noexcept; };
struct InvalidParentHash: virtual dev::Exception {};
struct InvalidNumber: virtual dev::Exception {};
struct InvalidContractAddress: virtual dev::Exception {};
struct InvalidContractAddress: virtual public dev::Exception {};
}
}

4
libethereum/BlockChain.h

@ -39,13 +39,15 @@ namespace ldb = leveldb;
namespace dev
{
class OverlayDB;
namespace eth
{
static const h256s NullH256s;
class State;
class OverlayDB;
struct AlreadyHaveBlock: virtual Exception {};
struct UnknownParent: virtual Exception {};

15
libethereum/Client.cpp

@ -88,8 +88,19 @@ void Client::setNetworkId(u256 _n)
h->setNetworkId(_n);
}
DownloadMan const* Client::downloadMan() const { if (auto h = m_host.lock()) return &(h->downloadMan()); return nullptr; }
bool Client::isSyncing() const { if (auto h = m_host.lock()) return h->isSyncing(); return false; }
DownloadMan const* Client::downloadMan() const
{
if (auto h = m_host.lock())
return &(h->downloadMan());
return nullptr;
}
bool Client::isSyncing() const
{
if (auto h = m_host.lock())
return h->isSyncing();
return false;
}
void Client::doneWorking()
{

5
libethereum/CommonNet.h

@ -30,6 +30,9 @@
namespace dev
{
class OverlayDB;
namespace eth
{
@ -44,7 +47,7 @@ static const unsigned c_maxHashesAsk = 256; ///< Maximum number of hashes GetBl
static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send.
static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
#endif
class OverlayDB;
class BlockChain;
class TransactionQueue;
class EthereumHost;

5
libethereum/EthereumHost.cpp

@ -86,6 +86,11 @@ void EthereumHost::noteNeedsSyncing(EthereumPeer* _who)
void EthereumHost::changeSyncer(EthereumPeer* _syncer)
{
if (_syncer)
clog(NetAllDetail) << "Changing syncer to" << _syncer->session()->socketId();
else
clog(NetAllDetail) << "Clearing syncer.";
m_syncer = _syncer;
if (isSyncing())
{

3
libethereum/EthereumPeer.cpp

@ -142,7 +142,6 @@ void EthereumPeer::transition(Asking _a, bool _force)
host()->m_man.resetToChain(m_syncingNeededBlocks);
host()->m_latestBlockSent = m_syncingLatestHash;
}
else
{
@ -156,7 +155,7 @@ void EthereumPeer::transition(Asking _a, bool _force)
if (m_asking == Asking::Nothing || m_asking == Asking::Hashes || m_asking == Asking::Blocks)
{
// Looks like it's the best yet for total difficulty. Set to download.
setAsking(Asking::Blocks, true); // will kick off other peers to help if available.
setAsking(Asking::Blocks, isSyncing()); // will kick off other peers to help if available.
auto blocks = m_sub.nextFetch(c_maxBlocksAsk);
if (blocks.size())
{

2
libethereum/MessageFilter.cpp

@ -36,7 +36,7 @@ h256 MessageFilter::sha3() const
{
RLPStream s;
fillStream(s);
return dev::eth::sha3(s.out());
return dev::sha3(s.out());
}
bool MessageFilter::matches(h256 _bloom) const

15
libethereum/State.cpp

@ -58,7 +58,7 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
int pubkeylen = 65;
secp256k1_start();
if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27))
ret = dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64));
ret = dev::sha3(bytesConstRef(&(pubkey[1]), 64));
memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret)));
}
@ -207,6 +207,19 @@ State::~State()
{
}
Address State::nextActiveAddress(Address _a) const
{
auto it = m_state.lower_bound(_a);
if ((*it).first == _a)
++it;
if (it == m_state.end())
// exchange comments if we want to wraparound
// it = m_state.begin();
return Address();
return (*it).first;
}
// TODO: repot
struct CachedAddressState
{
CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {}

3
libethereum/State.h

@ -40,6 +40,7 @@
namespace dev
{
namespace test { class FakeExtVM; class FakeState; }
namespace eth
@ -116,6 +117,8 @@ public:
/// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const;
Address nextActiveAddress(Address _a) const;
BlockInfo const& info() const { return m_currentBlock; }
/// @brief Checks that mining the current object will result in a valid block.

2
libethereum/Transaction.cpp

@ -81,7 +81,7 @@ Address Transaction::sender() const
BOOST_THROW_EXCEPTION(InvalidSignature());
// TODO: check right160 is correct and shouldn't be left160.
m_sender = right160(dev::eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
m_sender = right160(dev::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- RECOVER -------------------------------" << endl;

4
libethereum/Transaction.h

@ -67,8 +67,8 @@ struct Transaction
void fillStream(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); }
std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::eth::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::eth::sha3Bytes(s.out()); }
h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3Bytes(s.out()); }
private:
mutable Address m_sender;

2
libevm/VM.h

@ -41,7 +41,7 @@ struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {};
struct BadJumpDestination: virtual VMException {};
struct OutOfGas: virtual VMException {};
class StackTooSmall: public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; };
class StackTooSmall: virtual public VMException { public: StackTooSmall(u256 _req, u256 _got): req(_req), got(_got) {} u256 req; u256 got; };
// Convert from a 256-bit integer stack/memory entry into a 160-bit Address hash.
// Currently we just pull out the right (low-order in BE) 160-bits.

2
libp2p/Common.h

@ -127,5 +127,7 @@ struct PeerInfo
std::map<std::string, std::string> notes;
};
using PeerInfos = std::vector<PeerInfo>;
}
}

125
libp2p/Host.cpp

@ -61,8 +61,9 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
Worker("p2p"),
m_clientVersion(_clientVersion),
m_netPrefs(_n),
m_acceptor(m_ioService),
m_socket(m_ioService),
m_ioService(new ba::io_service),
m_acceptor(*m_ioService),
m_socket(*m_ioService),
m_key(KeyPair::create())
{
populateAddresses();
@ -73,11 +74,15 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
Host::~Host()
{
stop();
quit();
}
void Host::start()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (isWorking())
stop();
@ -105,14 +110,6 @@ void Host::start()
}
}
determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
ensureAccepting();
if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
noteNode(id(), m_public, Origin::Perfect, false);
clog(NetNote) << "Id:" << id().abridged();
for (auto const& h: m_capabilities)
h.second->onStarting();
@ -137,7 +134,18 @@ void Host::stop()
m_socket.close();
disconnectPeers();
if (!!m_ioService)
{
m_ioService->stop();
m_ioService->reset();
}
}
void Host::quit()
{
stop();
m_ioService.reset();
// m_acceptor & m_socket are DANGEROUS now.
}
unsigned Host::protocolVersion() const
@ -168,6 +176,10 @@ void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
void Host::disconnectPeers()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
for (unsigned n = 0;; n = 0)
{
{
@ -181,7 +193,7 @@ void Host::disconnectPeers()
}
if (!n)
break;
m_ioService.poll();
m_ioService->poll();
this_thread::sleep_for(chrono::milliseconds(100));
}
@ -204,6 +216,10 @@ void Host::seal(bytes& _b)
void Host::determinePublic(string const& _publicAddress, bool _upnp)
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (_upnp)
try
{
@ -211,7 +227,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
}
catch (NoUPnPDevice) {} // let m_upnp continue as null - we handle it properly.
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
if (m_upnp && m_upnp->isValid() && m_peerAddresses.size())
{
clog(NetNote) << "External addr:" << m_upnp->externalIP();
@ -249,6 +265,10 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
void Host::populateAddresses()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
#ifdef _WIN32
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
@ -289,7 +309,7 @@ void Host::populateAddresses()
if (getifaddrs(&ifaddr) == -1)
BOOST_THROW_EXCEPTION(NoNetworking());
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
for (ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next)
{
@ -349,7 +369,7 @@ shared_ptr<Node> Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, boo
if (_a.port() < 30300 && _a.port() > 30303)
cwarn << "Wierd port being recorded!";
if (_a.port() >= 49152)
if (_a.port() >= /*49152*/32768)
{
cwarn << "Private port being recorded - setting to 0";
_a = bi::tcp::endpoint(_a.address(), 0);
@ -422,6 +442,10 @@ Nodes Host::potentialPeers(RangeMask<unsigned> const& _known)
void Host::ensureAccepting()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (!m_accepting)
{
clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")";
@ -465,13 +489,17 @@ string Host::pocHost()
void Host::connect(std::string const& _addr, unsigned short _port) noexcept
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
for (int i = 0; i < 2; ++i)
{
try
{
if (i == 0)
{
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
connect(r.resolve({_addr, toString(_port)})->endpoint());
}
else
@ -493,8 +521,12 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept
void Host::connect(bi::tcp::endpoint const& _ep)
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
clog(NetConnect) << "Attempting single-shot connection to " << _ep;
bi::tcp::socket* s = new bi::tcp::socket(m_ioService);
bi::tcp::socket* s = new bi::tcp::socket(*m_ioService);
s->async_connect(_ep, [=](boost::system::error_code const& ec)
{
if (ec)
@ -509,27 +541,31 @@ void Host::connect(bi::tcp::endpoint const& _ep)
});
}
void Node::connect(Host* _h)
void Host::connect(std::shared_ptr<Node> const& _n)
{
clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address << "from" << _h->id().abridged();
lastAttempted = std::chrono::system_clock::now();
failedAttempts++;
_h->m_ready -= index;
bi::tcp::socket* s = new bi::tcp::socket(_h->m_ioService);
s->async_connect(address, [=](boost::system::error_code const& ec)
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
clog(NetConnect) << "Attempting connection to node" << _n->id.abridged() << "@" << _n->address << "from" << id().abridged();
_n->lastAttempted = std::chrono::system_clock::now();
_n->failedAttempts++;
m_ready -= _n->index;
bi::tcp::socket* s = new bi::tcp::socket(*m_ioService);
s->async_connect(_n->address, [=](boost::system::error_code const& ec)
{
if (ec)
{
clog(NetConnect) << "Connection refused to node" << id.abridged() << "@" << address << "(" << ec.message() << ")";
lastDisconnect = TCPError;
lastAttempted = std::chrono::system_clock::now();
_h->m_ready += index;
clog(NetConnect) << "Connection refused to node" << _n->id.abridged() << "@" << _n->address << "(" << ec.message() << ")";
_n->lastDisconnect = TCPError;
_n->lastAttempted = std::chrono::system_clock::now();
m_ready += _n->index;
}
else
{
clog(NetConnect) << "Connected to" << id.abridged() << "@" << address;
lastConnected = std::chrono::system_clock::now();
auto p = make_shared<Session>(_h, std::move(*s), _h->node(id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism.
clog(NetConnect) << "Connected to" << _n->id.abridged() << "@" << _n->address;
_n->lastConnected = std::chrono::system_clock::now();
auto p = make_shared<Session>(this, std::move(*s), node(_n->id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism.
p->start();
}
delete s;
@ -594,7 +630,7 @@ void Host::growPeers()
if (ns.size())
for (Node const& i: ns)
{
m_nodes[i.id]->connect(this);
connect(m_nodes[i.id]);
if (!--morePeers)
return;
}
@ -640,8 +676,12 @@ void Host::prunePeers()
i = m_peers.erase(i);
}
std::vector<PeerInfo> Host::peers(bool _updatePing) const
PeerInfos Host::peers(bool _updatePing) const
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return PeerInfos();
RecursiveGuard l(x_peers);
if (_updatePing)
{
@ -656,8 +696,23 @@ std::vector<PeerInfo> Host::peers(bool _updatePing) const
return ret;
}
void Host::startedWorking()
{
determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp);
ensureAccepting();
if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
noteNode(id(), m_public, Origin::Perfect, false);
clog(NetNote) << "Id:" << id().abridged();
}
void Host::doWork()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (asserts(!!m_ioService))
return;
growPeers();
prunePeers();
@ -679,7 +734,7 @@ void Host::doWork()
pingAll();
}
m_ioService.poll();
m_ioService->poll();
}
void Host::pingAll()
@ -701,7 +756,7 @@ bytes Host::saveNodes() const
{
Node const& n = *(i.second);
// TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 &&
if (!n.dead && n.address.port() > 0 && n.address.port() < 49152 && n.id != id() && !isPrivateAddress(n.address.address()))
if (!n.dead && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address()))
{
nodes.appendList(10);
if (n.address.address().is_v4())

13
libp2p/Host.h

@ -97,8 +97,6 @@ struct Node
else
return score < _n.score;
}
void connect(Host* _h);
};
using Nodes = std::vector<Node>;
@ -147,6 +145,7 @@ public:
static std::string pocHost();
void connect(std::string const& _addr, unsigned short _port = 30303) noexcept;
void connect(bi::tcp::endpoint const& _ep);
void connect(std::shared_ptr<Node> const& _n);
/// @returns true iff we have the a peer of the given id.
bool havePeer(NodeId _id) const;
@ -155,7 +154,7 @@ public:
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
/// Get peer information.
std::vector<PeerInfo> peers(bool _updatePing = false) const;
PeerInfos peers(bool _updatePing = false) const;
/// Get number of peers connected; equivalent to, but faster than, peers().size().
size_t peerCount() const { RecursiveGuard l(x_peers); return m_peers.size(); }
@ -174,12 +173,14 @@ public:
Nodes nodes() const { RecursiveGuard l(x_peers); Nodes ret; for (auto const& i: m_nodes) ret.push_back(*i.second); return ret; }
void setNetworkPreferences(NetworkPreferences const& _p) { stop(); m_netPrefs = _p; start(); }
void setNetworkPreferences(NetworkPreferences const& _p) { auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
void start();
void stop();
bool isStarted() const { return isWorking(); }
void quit();
NodeId id() const { return m_key.pub(); }
void registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps);
@ -195,6 +196,8 @@ private:
void growPeers();
void prunePeers();
virtual void startedWorking();
/// Conduct I/O, polling, syncing, whatever.
/// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway.
/// This won't touch alter the blockchain.
@ -210,7 +213,7 @@ private:
static const int NetworkStopped = -1; ///< The value meaning we're not actually listening.
int m_listenPort = NetworkStopped; ///< What port are we listening on?
ba::io_service m_ioService; ///< IOService for network stuff.
std::unique_ptr<ba::io_service> m_ioService; ///< IOService for network stuff.
bi::tcp::acceptor m_acceptor; ///< Listening acceptor.
bi::tcp::socket m_socket; ///< Listening socket.

4
libp2p/Session.cpp

@ -335,7 +335,7 @@ bool Session::interpret(RLP const& _r)
if (!ep.port())
goto CONTINUE; // Zero port? Don't think so.
if (ep.port() >= 49152)
if (ep.port() >= /*49152*/32768)
goto CONTINUE; // Private port according to IANA.
// TODO: PoC-7:
@ -582,7 +582,7 @@ void Session::doRead()
// error - bad protocol
clogS(NetWarn) << "Couldn't interpret packet." << RLP(r);
// Just wasting our bandwidth - perhaps reduce rating?
return;
//return;
}
}
memmove(m_incoming.data(), m_incoming.data() + tlen, m_incoming.size() - tlen);

2
libp2p/UPnP.h

@ -25,6 +25,7 @@
#include <set>
#include <string>
#include <memory>
#include <thread>
struct UPNPUrls;
struct IGDdatas;
@ -46,6 +47,7 @@ public:
bool isValid() const { return m_ok; }
private:
std::set<int> m_reg;
bool m_ok;
std::shared_ptr<struct UPNPUrls> m_urls;

111
libqethereum/QEthereum.cpp

@ -56,10 +56,11 @@ QString unpadded(QString _s)
}
QEthereum::QEthereum(QObject* _p, eth::Interface* _c, QList<dev::KeyPair> _accounts):
QObject(_p), m_client(_c), m_accounts(_accounts)
QObject(_p), m_client(_c)
{
// required to prevent crash on osx when performing addto/evaluatejavascript calls
moveToThread(_p->thread());
setAccounts(_accounts);
}
QEthereum::~QEthereum()
@ -81,11 +82,6 @@ void QEthereum::clearWatches()
m_watches.clear();
}
QString QEthereum::secretToAddress(QString _s) const
{
return toQJS(KeyPair(toSecret(_s)).address());
}
eth::Interface* QEthereum::client() const
{
return m_client;
@ -96,27 +92,22 @@ QString QEthereum::lll(QString _s) const
return toQJS(dev::eth::compileLLL(_s.toStdString()));
}
QString QEthereum::sha3(QString _s) const
{
return toQJS(dev::eth::sha3(toBytes(_s)));
}
QString QEthereum::sha3(QString _s1, QString _s2) const
QString QDev::sha3(QString _s) const
{
return toQJS(dev::eth::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32))));
return toQJS(dev::sha3(toBytes(_s)));
}
QString QEthereum::sha3(QString _s1, QString _s2, QString _s3) const
QString QDev::sha3(QString _s1, QString _s2) const
{
return toQJS(dev::eth::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)) + asBytes(padded(_s3, 32))));
return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32))));
}
QString QEthereum::sha3old(QString _s) const
QString QDev::sha3(QString _s1, QString _s2, QString _s3) const
{
return toQJS(dev::eth::sha3(asBytes(_s)));
return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)) + asBytes(padded(_s3, 32))));
}
QString QEthereum::offset(QString _s, int _i) const
QString QDev::offset(QString _s, int _i) const
{
return toQJS(toU256(_s) + _i);
}
@ -131,33 +122,11 @@ QString QEthereum::number() const
return m_client ? QString::number(client()->number() + 1) : "";
}
QString QEthereum::account() const
{
if (m_accounts.empty())
return toQJS(Address());
return toQJS(m_accounts[0].address());
}
QStringList QEthereum::accounts() const
{
QStringList ret;
for (auto i: m_accounts)
ret.push_back(toQJS(i.address()));
return ret;
}
QString QEthereum::key() const
{
if (m_accounts.empty())
return toQJS(KeyPair().sec());
return toQJS(m_accounts[0].sec());
}
QStringList QEthereum::keys() const
{
QStringList ret;
for (auto i: m_accounts)
ret.push_back(toQJS(i.sec()));
ret.push_back(toQJS(i.first));
return ret;
}
@ -269,7 +238,7 @@ static dev::eth::MessageFilter toMessageFilter(QString _json)
struct TransactionSkeleton
{
Secret from;
Address from;
Address to;
u256 value;
bytes data;
@ -283,7 +252,7 @@ static TransactionSkeleton toTransaction(QString _json)
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("from"))
ret.from = toSecret(f["from"].toString());
ret.from = toAddress(f["from"].toString());
if (f.contains("to"))
ret.to = toAddress(f["to"].toString());
if (f.contains("value"))
@ -458,26 +427,17 @@ void QEthereum::setListening(bool)
client()->stopNetwork();*/
}
unsigned QEthereum::peerCount() const
void QEthereum::setAccounts(QList<dev::KeyPair> const& _l)
{
return /*m_client ? (unsigned)client()->peerCount() :*/ 0;
m_accounts.clear();
for (auto i: _l)
m_accounts[i.address()] = i.secret();
keysChanged();
}
QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice)
{
if (!m_client)
return "";
auto ret = toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice)));
client()->flushTransactions();
return ret;
}
void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice)
unsigned QEthereum::peerCount() const
{
if (!m_client)
return;
client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice));
client()->flushTransactions();
return /*m_client ? (unsigned)client()->peerCount() :*/ 0;
}
QString QEthereum::doTransact(QString _json)
@ -488,18 +448,23 @@ QString QEthereum::doTransact(QString _json)
TransactionSkeleton t = toTransaction(_json);
if (!t.from && m_accounts.size())
{
auto b = m_accounts.first();
auto b = m_accounts.begin()->first;
for (auto a: m_accounts)
if (client()->balanceAt(KeyPair(a).address()) > client()->balanceAt(KeyPair(b).address()))
b = a;
t.from = b.secret();
if (client()->balanceAt(a.first) > client()->balanceAt(b))
b = a.first;
t.from = b;
}
if (!m_accounts.count(t.from))
return QString();
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas)
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(KeyPair(t.from).address()) / t.gasPrice);
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
cwarn << "Silently signing transaction from address" << t.from.abridged() << ": User validation hook goes here.";
if (t.to)
client()->transact(t.from, t.value, t.to, t.data, t.gas, t.gasPrice);
// TODO: insert validification hook here.
client()->transact(m_accounts[t.from].secret(), t.value, t.to, t.data, t.gas, t.gasPrice);
else
ret = toQJS(client()->transact(t.from, t.value, t.data, t.gas, t.gasPrice));
client()->flushTransactions();
@ -511,15 +476,21 @@ QString QEthereum::doCall(QString _json)
if (!m_client)
return QString();
TransactionSkeleton t = toTransaction(_json);
if (!t.to)
return QString();
if (!t.from && m_accounts.size())
t.from = m_accounts[0].secret();
{
auto b = m_accounts.begin()->first;
for (auto a: m_accounts)
if (client()->balanceAt(a.first) > client()->balanceAt(b))
b = a.first;
t.from = b;
}
if (!m_accounts.count(t.from))
return QString();
if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas)
t.gas = client()->balanceAt(KeyPair(t.from).address()) / t.gasPrice;
bytes out = client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice);
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
bytes out = client()->call(m_accounts[t.from].secret(), t.value, t.to, t.data, t.gas, t.gasPrice);
return asQString(out);
}

90
libqethereum/QEthereum.h

@ -98,6 +98,27 @@ inline QString fromBinary(QString const& _s, unsigned _padding = 32)
return fromBinary(asBytes(_s), _padding);
}
class QDev: public QObject
{
Q_OBJECT
public:
QDev(QObject* _p): QObject(_p) {}
virtual ~QDev() {}
Q_INVOKABLE QString sha3(QString _s) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2, QString _s3) const;
Q_INVOKABLE QString offset(QString _s, int _offset) const;
Q_INVOKABLE QString toAscii(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromAscii(QString _s) const { return ::fromBinary(_s, 32); }
Q_INVOKABLE QString fromAscii(QString _s, unsigned _padding) const { return ::fromBinary(_s, _padding); }
Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); }
Q_INVOKABLE double fromFixed(QString _s) const { return ::fromFixed(_s); }
Q_INVOKABLE QString toFixed(double _d) const { return ::toFixed(_d); }
};
class QEthereum: public QObject
{
Q_OBJECT
@ -112,31 +133,12 @@ public:
/// Call when the client() is going to be deleted to make this object useless but safe.
void clientDieing();
void setAccounts(QList<dev::KeyPair> _l) { m_accounts = _l; keysChanged(); }
void setAccounts(QList<dev::KeyPair> const& _l);
Q_INVOKABLE QString ethTest() const { return "Hello world!"; }
Q_INVOKABLE QEthereum* self() { return this; }
Q_INVOKABLE QString secretToAddress(QString _s) const;
Q_INVOKABLE QString lll(QString _s) const;
Q_INVOKABLE QString sha3(QString _s) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2) const;
Q_INVOKABLE QString sha3(QString _s1, QString _s2, QString _s3) const;
Q_INVOKABLE QString sha3old(QString _s) const;
Q_INVOKABLE QString offset(QString _s, int _offset) const;
Q_INVOKABLE QString pad(QString _s, unsigned _l) const { return padded(_s, _l); }
Q_INVOKABLE QString pad(QString _s, unsigned _l, unsigned _r) const { return padded(_s, _l, _r); }
Q_INVOKABLE QString unpad(QString _s) const { return unpadded(_s); }
Q_INVOKABLE QString toAscii(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromAscii(QString _s) const { return ::fromBinary(_s, 32); }
Q_INVOKABLE QString fromAscii(QString _s, unsigned _padding) const { return ::fromBinary(_s, _padding); }
Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); }
Q_INVOKABLE double fromFixed(QString _s) const { return ::fromFixed(_s); }
Q_INVOKABLE QString toFixed(double _d) const { return ::toFixed(_d); }
// [NEW API] - Use this instead.
Q_INVOKABLE QString/*dev::u256*/ balanceAt(QString/*dev::Address*/ _a, int _block) const;
Q_INVOKABLE double countAt(QString/*dev::Address*/ _a, int _block) const;
@ -154,8 +156,6 @@ public:
Q_INVOKABLE QString/*json*/ getMessages(QString _attribs/*json*/) const;
Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice);
Q_INVOKABLE void doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice);
Q_INVOKABLE QString doTransact(QString _json);
Q_INVOKABLE QString doCall(QString _json);
@ -172,9 +172,6 @@ public:
QString/*dev::u256*/ number() const;
int getDefault() const;
QString/*dev::KeyPair*/ key() const;
QStringList/*list of dev::KeyPair*/ keys() const;
QString/*dev::Address*/ account() const;
QStringList/*list of dev::Address*/ accounts() const;
unsigned peerCount() const;
@ -200,8 +197,7 @@ private:
Q_PROPERTY(QString number READ number NOTIFY watchChanged)
Q_PROPERTY(QString coinbase READ coinbase WRITE setCoinbase NOTIFY coinbaseChanged)
Q_PROPERTY(QString gasPrice READ gasPrice)
Q_PROPERTY(QString key READ key NOTIFY keysChanged)
Q_PROPERTY(QStringList keys READ keys NOTIFY keysChanged)
Q_PROPERTY(QStringList accounts READ accounts NOTIFY keysChanged)
Q_PROPERTY(bool mining READ isMining WRITE setMining NOTIFY netChanged)
Q_PROPERTY(bool listening READ isListening WRITE setListening NOTIFY netChanged)
Q_PROPERTY(unsigned peerCount READ peerCount NOTIFY miningChanged)
@ -209,7 +205,7 @@ private:
dev::eth::Interface* m_client;
std::vector<unsigned> m_watches;
QList<dev::KeyPair> m_accounts;
std::map<dev::Address, dev::KeyPair> m_accounts;
};
class QWhisper: public QObject
@ -251,22 +247,30 @@ private:
std::vector<unsigned> m_watches;
};
#define QETH_INSTALL_JS_NAMESPACE(frame, eth, shh, env) [frame, eth, shh, env]() \
// TODO: add p2p object
#define QETH_INSTALL_JS_NAMESPACE(_frame, _env, _dev, _eth, _shh) [_frame, _env, _dev, _eth, _shh]() \
{ \
_frame->disconnect(); \
_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
_frame->addToJavaScriptWindowObject("dev", _dev, QWebFrame::ScriptOwnership); \
if (_eth) \
{ \
_frame->addToJavaScriptWindowObject("eth", _eth, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \
_frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \
_frame->evaluateJavaScript("eth.transact = function(a, f) { var r = eth.doTransact(JSON.stringify(a)); if (f) f(r); }"); \
_frame->evaluateJavaScript("eth.call = function(a, f) { var ret = eth.doCallJson(JSON.stringify(a)); if (f) f(ret); return ret; }"); \
_frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \
_frame->evaluateJavaScript("eth.block = function(a) { return JSON.parse(eth.getBlock(a)); }"); \
_frame->evaluateJavaScript("eth.transaction = function(a) { return JSON.parse(eth.getTransaction(a)); }"); \
_frame->evaluateJavaScript("eth.uncle = function(a) { return JSON.parse(eth.getUncle(a)); }"); \
} \
if (_shh) \
{ \
frame->disconnect(); \
frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \
frame->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \
frame->addToJavaScriptWindowObject("shh", eth, QWebFrame::ScriptOwnership); \
frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \
frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \
frame->evaluateJavaScript("eth.transact = function(a, f) { var r = eth.doTransact(JSON.stringify(a)); if (f) f(r); }"); \
frame->evaluateJavaScript("eth.call = function(a, f) { var ret = eth.doCallJson(JSON.stringify(a)); if (f) f(ret); return ret; }"); \
frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \
frame->evaluateJavaScript("eth.block = function(a) { return JSON.parse(eth.getBlock(a)); }"); \
frame->evaluateJavaScript("eth.transaction = function(a) { return JSON.parse(eth.getTransaction(a)); }"); \
frame->evaluateJavaScript("eth.uncle = function(a) { return JSON.parse(eth.getUncle(a)); }"); \
frame->evaluateJavaScript("shh.makeWatch = function(a) { var ww = shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { shh.killWatch(w); }; ret.changed = function(f) { shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(shh.watchMessages(this.w)) }; return ret; }"); \
frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \
_frame->addToJavaScriptWindowObject("shh", _shh, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("shh.makeWatch = function(a) { var ww = shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { shh.killWatch(w); }; ret.changed = function(f) { shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(shh.watchMessages(this.w)) }; return ret; }"); \
_frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \
} \
}
template <unsigned N> inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>> toInt(QString const& _s)

22
libwebthree/WebThree.cpp

@ -51,6 +51,28 @@ WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string co
WebThreeDirect::~WebThreeDirect()
{
// Utterly horrible right now - WebThree owns everything (good), but:
// m_net (Host) owns the eth::EthereumHost via a shared_ptr.
// The eth::EthereumHost depends on eth::Client (it maintains a reference to the BlockChain field of Client).
// eth::Client (owned by us via a unique_ptr) uses eth::EthereumHost (via a weak_ptr).
// Really need to work out a clean way of organising ownership and guaranteeing startup/shutdown is perfect.
// Have to call quit here to get the Host to kill its io_service otherwise we end up with left-over reads,
// still referencing Sessions getting deleted *after* m_ethereum is reset, causing bad things to happen, since
// the guarantee is that m_ethereum is only reset *after* all sessions have ended (sessions are allowed to
// use bits of data owned by m_ethereum).
m_net.quit();
m_ethereum.reset();
}
void WebThreeDirect::setNetworkPreferences(p2p::NetworkPreferences const& _n)
{
auto had = haveNetwork();
if (had)
stopNetwork();
m_net.setNetworkPreferences(_n);
if (had)
startNetwork();
}
std::vector<PeerInfo> WebThreeDirect::peers()

6
libwebthree/WebThree.h

@ -106,7 +106,7 @@ public:
bool haveNetwork() const { return m_net.isStarted(); }
void setNetworkPreferences(p2p::NetworkPreferences const& _n) { auto had = haveNetwork(); if (had) stopNetwork(); m_net.setNetworkPreferences(_n); if (had) startNetwork(); }
void setNetworkPreferences(p2p::NetworkPreferences const& _n);
p2p::NodeId id() const { return m_net.id(); }
@ -122,10 +122,10 @@ public:
private:
std::string m_clientVersion; ///< Our end-application client's name/version.
p2p::Host m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
std::unique_ptr<eth::Client> m_ethereum; ///< Main interface for Ethereum ("eth") protocol.
std::weak_ptr<shh::WhisperHost> m_whisper; ///< Main interface for Whisper ("shh") protocol.
p2p::Host m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
};

2
libwhisper/Common.h

@ -57,5 +57,7 @@ enum WhisperPacket
PacketCount
};
using Topic = h256;
}
}

11
libwhisper/Interface.cpp

@ -36,15 +36,8 @@ using namespace dev::shh;
bool MessageFilter::matches(Message const& _m) const
{
for (auto const& t: m_topicMasks)
{
if (t.first.size() != t.second.size() || _m.topic.size() < t.first.size())
continue;
for (unsigned i = 0; i < t.first.size(); ++i)
if (((t.first[i] ^ _m.topic[i]) & t.second[i]) != 0)
goto NEXT;
for (TopicMask const& t: m_topicMasks)
if (((t.first ^ _m.topic) & t.second) == 0)
return true;
NEXT:;
}
return false;
}

19
libwhisper/Interface.h

@ -37,20 +37,29 @@ namespace dev
namespace shh
{
/*struct TopicMask
{
Topic data;
Topic mask;
};*/
using TopicMask = std::pair<Topic, Topic>;
using TopicMasks = std::vector<TopicMask>;
class MessageFilter
{
public:
MessageFilter() {}
MessageFilter(std::vector<std::pair<bytes, bytes> > const& _m): m_topicMasks(_m) {}
MessageFilter(RLP const& _r): m_topicMasks((std::vector<std::pair<bytes, bytes>>)_r) {}
MessageFilter(TopicMasks const& _m): m_topicMasks(_m) {}
MessageFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
void fillStream(RLPStream& _s) const { _s << m_topicMasks; }
h256 sha3() const { RLPStream s; fillStream(s); return dev::eth::sha3(s.out()); }
h256 sha3() const { RLPStream s; fillStream(s); return dev::sha3(s.out()); }
bool matches(Message const& _m) const;
private:
std::vector<std::pair<bytes, bytes> > m_topicMasks;
TopicMasks m_topicMasks;
};
struct InstalledFilter
@ -85,7 +94,7 @@ public:
virtual Message message(h256 _m) const = 0;
virtual void sendRaw(bytes const& _payload, bytes const& _topic, unsigned _ttl) = 0;
virtual void sendRaw(bytes const& _payload, h256 _topic, unsigned _ttl) = 0;
};
struct WatshhChannel: public dev::LogChannel { static const char* name() { return "shh"; } static const int verbosity = 1; };

8
libwhisper/Message.h

@ -40,23 +40,23 @@ struct Message
{
unsigned expiry = 0;
unsigned ttl = 0;
bytes topic; // TODO: change to h256
Topic topic; // TODO: change to h256
bytes payload;
Message() {}
Message(unsigned _exp, unsigned _ttl, bytes const& _topic, bytes const& _payload): expiry(_exp), ttl(_ttl), topic(_topic), payload(_payload) {}
Message(unsigned _exp, unsigned _ttl, Topic const& _topic, bytes const& _payload): expiry(_exp), ttl(_ttl), topic(_topic), payload(_payload) {}
Message(RLP const& _m)
{
expiry = _m[0].toInt<unsigned>();
ttl = _m[1].toInt<unsigned>();
topic = _m[2].toBytes();
topic = (Topic)_m[2];
payload = _m[3].toBytes();
}
operator bool () const { return !!expiry; }
void streamOut(RLPStream& _s) const { _s.appendList(4) << expiry << ttl << topic << payload; }
h256 sha3() const { RLPStream s; streamOut(s); return dev::eth::sha3(s.out()); }
h256 sha3() const { RLPStream s; streamOut(s); return dev::sha3(s.out()); }
};
}

2
libwhisper/WhisperHost.h

@ -58,7 +58,7 @@ public:
virtual Message message(h256 _m) const { try { dev::ReadGuard l(x_messages); return m_messages.at(_m); } catch (...) { return Message(); } }
virtual void sendRaw(bytes const& _payload, bytes const& _topic, unsigned _ttl) { inject(Message(time(0) + _ttl, _ttl, _topic, _payload)); }
virtual void sendRaw(bytes const& _payload, Topic _topic, unsigned _ttl) { inject(Message(time(0) + _ttl, _ttl, _topic, _payload)); }
private:
void streamMessage(h256 _m, RLPStream& _s) const;

2
neth/main.cpp

@ -805,7 +805,7 @@ int main(int argc, char** argv)
cnote << "Saved" << rechex << "to" << outFile;
}
catch (dev::eth::InvalidTrie const& _e)
catch (dev::InvalidTrie const& _e)
{
cwarn << "Corrupted trie.\n" << diagnostic_information(_e);
}

39
qtcreator-style.xml

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorCodeStyle>
<!-- Written by QtCreator 3.0.1, 2014-10-16T20:02:31. -->
<qtcreator>
<data>
<variable>CodeStyleData</variable>
<valuemap type="QVariantMap">
<value type="bool" key="AlignAssignments">false</value>
<value type="bool" key="AutoSpacesForTabs">false</value>
<value type="bool" key="BindStarToIdentifier">true</value>
<value type="bool" key="BindStarToLeftSpecifier">false</value>
<value type="bool" key="BindStarToRightSpecifier">false</value>
<value type="bool" key="BindStarToTypeName">false</value>
<value type="bool" key="ExtraPaddingForConditionsIfConfusingAlign">true</value>
<value type="bool" key="IndentAccessSpecifiers">false</value>
<value type="bool" key="IndentBlockBody">true</value>
<value type="bool" key="IndentBlockBraces">false</value>
<value type="bool" key="IndentBlocksRelativeToSwitchLabels">false</value>
<value type="bool" key="IndentClassBraces">false</value>
<value type="bool" key="IndentControlFlowRelativeToSwitchLabels">true</value>
<value type="bool" key="IndentDeclarationsRelativeToAccessSpecifiers">true</value>
<value type="bool" key="IndentEnumBraces">false</value>
<value type="bool" key="IndentFunctionBody">true</value>
<value type="bool" key="IndentFunctionBraces">false</value>
<value type="bool" key="IndentNamespaceBody">false</value>
<value type="bool" key="IndentNamespaceBraces">false</value>
<value type="int" key="IndentSize">4</value>
<value type="bool" key="IndentStatementsRelativeToSwitchLabels">true</value>
<value type="bool" key="IndentSwitchLabels">false</value>
<value type="int" key="PaddingMode">2</value>
<value type="bool" key="SpacesForTabs">false</value>
<value type="int" key="TabSize">4</value>
</valuemap>
</data>
<data>
<variable>DisplayName</variable>
<value type="QString">Gav</value>
</data>
</qtcreator>

7
test/CMakeLists.txt

@ -1,6 +1,7 @@
cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST)
list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp")
include_directories(..)
link_directories(../libethcore)
@ -8,6 +9,7 @@ link_directories(../libethereum)
file(GLOB HEADERS "*.h")
add_executable(testeth ${SRC_LIST} ${HEADERS})
add_executable(createRandomTest createRandomTest.cpp vm.cpp)
target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore)
@ -15,6 +17,11 @@ target_link_libraries(testeth secp256k1)
target_link_libraries(testeth gmp)
target_link_libraries(testeth ${CRYPTOPP_LS})
target_link_libraries(createRandomTest ethereum)
target_link_libraries(createRandomTest ethcore)
target_link_libraries(createRandomTest boost_chrono)
target_link_libraries(createRandomTest boost_unit_test_framework)
if ("${TARGET_PLATFORM}" STREQUAL "w64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
target_link_libraries(testeth boost_system-mt-s)

4
test/MemTrie.cpp

@ -55,7 +55,7 @@ public:
#endif
/// 256-bit hash of the node - this is a SHA-3/256 hash of the RLP of the node.
h256 hash256() const { RLPStream s; makeRLP(s); return dev::eth::sha3(s.out()); }
h256 hash256() const { RLPStream s; makeRLP(s); return dev::sha3(s.out()); }
bytes rlp() const { RLPStream s; makeRLP(s); return s.out(); }
void mark() { m_hash256 = h256(); }
@ -200,7 +200,7 @@ void MemTrieNode::putRLP(RLPStream& _parentStream) const
if (s.out().size() < 32)
_parentStream.APPEND_CHILD(s.out());
else
_parentStream << dev::eth::sha3(s.out());
_parentStream << dev::sha3(s.out());
}
void TrieBranchNode::makeRLP(RLPStream& _intoStream) const

11
test/TestHelperCrypto.h

@ -22,11 +22,22 @@
#pragma once
//#include <ostream>
#pragma warning(push)
#pragma warning(disable:4100 4244)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic ignored "-Wextra"
#include <eccrypto.h>
#include <ecp.h>
#include <files.h>
#include <osrng.h>
#include <oids.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
using namespace std;
using namespace CryptoPP;

152
test/createRandomTest.cpp

@ -0,0 +1,152 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file createRandomTest.cpp
* @author Christoph Jentzsch <jentzsch.simulationsoftware@gmail.com>
* @date 2014
* Creating a random virtual machine test.
*/
#include <string>
#include <iostream>
#include <chrono>
#include <boost/random.hpp>
#include <boost/filesystem/path.hpp>
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <json_spirit/json_spirit.h>
#include <json_spirit/json_spirit_reader_template.h>
#include <json_spirit/json_spirit_writer_template.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmface/Instruction.h>
#include "vm.h"
using namespace std;
using namespace json_spirit;
using namespace dev;
void doMyTests(json_spirit::mValue& v);
int main(int argc, char *argv[])
{
if (argc != 2)
{
cout << "usage: createRandomTest <filename>\n";
return 0;
}
// create random code
boost::random::mt19937 gen;
auto now = chrono::steady_clock::now().time_since_epoch();
auto timeSinceEpoch = chrono::duration_cast<chrono::nanoseconds>(now).count();
gen.seed(static_cast<unsigned int>(timeSinceEpoch));
boost::random::uniform_int_distribution<> lengthOfCodeDist(2, 16);
boost::random::uniform_int_distribution<> opcodeDist(0, 255);
boost::random::variate_generator<boost::mt19937&,
boost::random::uniform_int_distribution<> > randGen(gen, opcodeDist);
int lengthOfCode = lengthOfCodeDist(gen);
string randomCode;
for (int i = 0; i < lengthOfCode; ++i)
randomCode += toHex(toCompactBigEndian(randGen()));
// read template test file
mValue v;
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(contents(dir.string() + "/randomTestFiller.json"));
read_string(s, v);
// insert new random code
v.get_obj().find("randomVMtest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode;
// execute code in vm
doMyTests(v);
// write new test
string filename = argv[1];
writeFile(filename, asBytes(json_spirit::write_string(v, true)));
return 0;
}
void doMyTests(json_spirit::mValue& v)
{
for (auto& i: v.get_obj())
{
mObject& o = i.second.get_obj();
assert(o.count("env") > 0);
assert(o.count("pre") > 0);
assert(o.count("exec") > 0);
eth::VM vm;
test::FakeExtVM fev;
fev.importEnv(o["env"].get_obj());
fev.importState(o["pre"].get_obj());
o["pre"] = mValue(fev.exportState());
fev.importExec(o["exec"].get_obj());
if (!fev.code)
{
fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress));
fev.code = &fev.thisTxCode;
}
vm.reset(fev.gas);
bytes output;
try
{
output = vm.go(fev).toBytes();
}
catch (Exception const& _e)
{
cnote << "VM did throw an exception: " << diagnostic_information(_e);
}
catch (std::exception const& _e)
{
cnote << "VM did throw an exception: " << _e.what();
}
// delete null entries in storage for the sake of comparison
for (auto &a: fev.addresses)
{
vector<u256> keystoDelete;
for (auto &s: get<2>(a.second))
{
if (s.second == 0)
keystoDelete.push_back(s.first);
}
for (auto const key: keystoDelete )
{
get<2>(a.second).erase(key);
}
}
o["env"] = mValue(fev.exportEnv());
o["exec"] = mValue(fev.exportExec());
o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output);
fev.push(o, "gas", vm.gas());
}
}

2
test/crypto.cpp

@ -307,7 +307,7 @@ int cryptoTest()
int ret = secp256k1_ecdsa_recover_compact((byte const*)hmsg.data(), (int)hmsg.size(), (byte const*)sig64.data(), pubkey.data(), &pubkeylen, 0, (int)t.vrs.v - 27);
pubkey.resize(pubkeylen);
cout << "RECPUB: " << dec << ret << " " << pubkeylen << " " << toHex(pubkey) << endl;
cout << "SENDER: " << hex << toAddress(dev::eth::sha3(bytesConstRef(&pubkey).cropped(1))) << dec << endl;
cout << "SENDER: " << hex << toAddress(dev::sha3(bytesConstRef(&pubkey).cropped(1))) << dec << endl;
}
#endif
return 0;

1
test/hexPrefix.cpp

@ -29,7 +29,6 @@
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;
BOOST_AUTO_TEST_CASE(hexPrefix_test)

29
test/randomTestFiller.json

@ -0,0 +1,29 @@
{
"randomVMtest": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "random",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
}
}

2
test/rlp.cpp

@ -79,7 +79,7 @@ namespace dev
if ( v.type() == js::str_type )
{
const std::string& expectedText = v.get_str();
if ( expectedText.front() == '#' )
if ( !expectedText.empty() && expectedText.front() == '#' )
{
// Deal with bigint instead of a raw string
std::string bigIntStr = expectedText.substr(1,expectedText.length()-1);

46
test/trie.cpp

@ -31,7 +31,6 @@
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;
@ -236,6 +235,51 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
}
}
BOOST_AUTO_TEST_CASE(trieLowerBound)
{
cnote << "Stress-testing Trie.lower_bound...";
{
MemoryDB dm;
EnforceRefs e(dm, true);
GenericTrieDB<MemoryDB> d(&dm);
d.init(); // initialise as empty tree.
for (int a = 0; a < 20; ++a)
{
StringMap m;
for (int i = 0; i < 50; ++i)
{
auto k = randomWord();
auto v = toString(i);
m[k] = v;
d.insert(k, v);
}
for (auto i: d)
{
auto it = d.lower_bound(i.first);
for (auto iit = d.begin(); iit != d.end(); ++iit)
if ((*iit).first.toString() >= i.first.toString())
{
BOOST_REQUIRE(it == iit);
break;
}
}
for (unsigned i = 0; i < 100; ++i)
{
auto k = randomWord();
auto it = d.lower_bound(k);
for (auto iit = d.begin(); iit != d.end(); ++iit)
if ((*iit).first.toString() >= k)
{
BOOST_REQUIRE(it == iit);
break;
}
}
}
}
}
BOOST_AUTO_TEST_CASE(trieStess)
{
cnote << "Stress-testing Trie...";

74
test/vm.cpp

@ -22,6 +22,7 @@
#include "vm.h"
#include <libdevcore/CommonIO.h>
#include <boost/filesystem/path.hpp>
#define FILL_TESTS
@ -97,7 +98,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{
cnote << "not able to call to : " << myAddress << "\n";
cnote << "in FakeExtVM you can only make a call to " << na << "\n";
BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(myAddress));
BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(toString(myAddress)));
return false;
}
}
@ -123,7 +124,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{
cnote << "not able to call to : " << (_codeAddressOverride ? _codeAddressOverride : _receiveAddress) << "\n";
cnote << "in FakeExtVM you can only make a call to " << na << "\n";
BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress));
BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(toString(_codeAddressOverride ? _codeAddressOverride : _receiveAddress)));
return false;
}
}
@ -251,12 +252,13 @@ mObject FakeExtVM::exportEnv()
void FakeExtVM::importEnv(mObject& _o)
{
BOOST_REQUIRE(_o.count("previousHash") > 0);
BOOST_REQUIRE(_o.count("currentGasLimit") > 0);
BOOST_REQUIRE(_o.count("currentDifficulty") > 0);
BOOST_REQUIRE(_o.count("currentTimestamp") > 0);
BOOST_REQUIRE(_o.count("currentCoinbase") > 0);
BOOST_REQUIRE(_o.count("currentNumber") > 0);
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert(_o.count("previousHash") > 0);
assert(_o.count("currentGasLimit") > 0);
assert(_o.count("currentDifficulty") > 0);
assert(_o.count("currentTimestamp") > 0);
assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0);
previousBlock.hash = h256(_o["previousHash"].get_str());
currentBlock.number = toInt(_o["currentNumber"]);
@ -293,10 +295,11 @@ void FakeExtVM::importState(mObject& _object)
for (auto const& i: _object)
{
mObject o = i.second.get_obj();
BOOST_REQUIRE(o.count("balance") > 0);
BOOST_REQUIRE(o.count("nonce") > 0);
BOOST_REQUIRE(o.count("storage") > 0);
BOOST_REQUIRE(o.count("code") > 0);
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert(o.count("balance") > 0);
assert(o.count("nonce") > 0);
assert(o.count("storage") > 0);
assert(o.count("code") > 0);
auto& a = addresses[Address(i.first)];
get<0>(a) = toInt(o["balance"]);
@ -334,13 +337,14 @@ mObject FakeExtVM::exportExec()
void FakeExtVM::importExec(mObject& _o)
{
BOOST_REQUIRE(_o.count("address")> 0);
BOOST_REQUIRE(_o.count("caller") > 0);
BOOST_REQUIRE(_o.count("origin") > 0);
BOOST_REQUIRE(_o.count("value") > 0);
BOOST_REQUIRE(_o.count("data") > 0);
BOOST_REQUIRE(_o.count("gasPrice") > 0);
BOOST_REQUIRE(_o.count("gas") > 0);
// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
assert(_o.count("address")> 0);
assert(_o.count("caller") > 0);
assert(_o.count("origin") > 0);
assert(_o.count("value") > 0);
assert(_o.count("data") > 0);
assert(_o.count("gasPrice") > 0);
assert(_o.count("gas") > 0);
myAddress = Address(_o["address"].get_str());
caller = Address(_o["caller"].get_str());
@ -493,7 +497,6 @@ void doTests(json_spirit::mValue& v, bool _fillin)
BOOST_REQUIRE(o.count("pre") > 0);
BOOST_REQUIRE(o.count("exec") > 0);
VM vm;
dev::test::FakeExtVM fev;
fev.importEnv(o["env"].get_obj());
fev.importState(o["pre"].get_obj());
@ -508,11 +511,13 @@ void doTests(json_spirit::mValue& v, bool _fillin)
fev.code = &fev.thisTxCode;
}
vm.reset(fev.gas);
bytes output;
u256 gas;
try
{
output = vm.go(fev).toBytes();
VM vm(fev.gas);
output = vm.go(fev).toVector();
gas = vm.gas(); // Get the remaining gas
}
catch (Exception const& _e)
{
@ -549,7 +554,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output);
fev.push(o, "gas", vm.gas());
fev.push(o, "gas", gas);
}
else
{
@ -573,7 +578,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
else
BOOST_CHECK(output == fromHex(o["out"].get_str()));
BOOST_CHECK(test.toInt(o["gas"]) == vm.gas());
BOOST_CHECK(test.toInt(o["gas"]) == gas);
BOOST_CHECK(test.addresses == fev.addresses);
BOOST_CHECK(test.callcreates == fev.callcreates);
}
@ -610,16 +615,29 @@ void doTests(json_spirit::mValue& v, bool _fillin)
void executeTests(const string& _name)
{
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
string testPath;
if (ptestPath == NULL)
{
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
testPath = "../../../tests/vmtests";
}
else
testPath = ptestPath;
#ifdef FILL_TESTS
try
{
cnote << "Populating VM tests...";
json_spirit::mValue v;
string s = asString(contents("../../../cpp-ethereum/test/" + _name + "Filler.json"));
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(contents(dir.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + "Filler.json is empty.");
json_spirit::read_string(s, v);
dev::test::doTests(v, true);
writeFile("../../../tests/vmtests/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));
}
catch (Exception const& _e)
{
@ -635,8 +653,8 @@ void executeTests(const string& _name)
{
cnote << "Testing VM..." << _name;
json_spirit::mValue v;
string s = asString(contents("../../../tests/vmtests/" + _name + ".json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop?");
string s = asString(contents(testPath + "/" + _name + ".json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
json_spirit::read_string(s, v);
dev::test::doTests(v, false);
}

85
test/vmArithmeticTestFiller.json

@ -281,6 +281,91 @@
}
},
"mul4": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (* 0x8000000000000000000000000000000000000000000000000000000000000000 115792089237316195423570985008687907853269984665640564039457584007913129639935) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"mul5": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (* 0x8000000000000000000000000000000000000000000000000000000000000000 0x8000000000000000000000000000000000000000000000000000000000000000) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"mul6": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ [[ 0 ]] (* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) }",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"sub0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

83
test/vmIOandFlowOperationsTestFiller.json

@ -530,6 +530,61 @@
"gas" : "10000"
}
},
"jump0_jumpdest0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x602360085860015d600257",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"jump0_jumpdest1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x602360075860015d600257",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"jumpi0": {
"env" : {
@ -559,6 +614,34 @@
}
},
"jumpi1_jumpdest": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "1000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x60236001600a5960015d600257",
"storage": {}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "1000000000000000000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000"
}
},
"jumpi1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

100
test/vmSystemOperationsTestFiller.json

@ -129,7 +129,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -255,6 +255,42 @@
}
},
"callcodeToReturn1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "10000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALLCODE 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 0 2 ) }",
"storage": {}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x6001600157603760005560026000f2",
"nonce" : "0",
"storage" : {
}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "100000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000000000000"
}
},
"CallToNameRegistratorOutOfGas": {
"env" : {
@ -274,7 +310,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -310,7 +346,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -346,7 +382,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -382,7 +418,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -419,7 +455,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -455,7 +491,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -525,7 +561,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -561,7 +597,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -597,7 +633,7 @@
},
"cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -723,7 +759,7 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -759,7 +795,43 @@
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
}
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : "100000",
"data" : "",
"gasPrice" : "100000000000000",
"gas" : "10000000000000"
}
},
"callcodeToNameRegistrator0": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "10000000",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALLCODE 1000000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }",
"storage": {}
},
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23",
"code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0",
"storage" : {
}
@ -790,7 +862,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : 0,
"code" : "0x600035560f6009590060203560003557",
"code" : "0x600035560f600a59005d60203560003557",
"storage": {}
}
},
@ -841,7 +913,7 @@
}
},
"ABAcalls0": {
"ABAcalls1": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",

4
third/MainWin.cpp

@ -105,14 +105,16 @@ Main::Main(QWidget *parent) :
connect(ui->webView, &QWebView::loadStarted, [this]()
{
// NOTE: no need to delete as QETH_INSTALL_JS_NAMESPACE adopts it.
m_dev = new QDev(this);
m_ethereum = new QEthereum(this, ethereum(), owned());
m_whisper = new QWhisper(this, whisper());
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
auto qdev = m_dev;
auto qeth = m_ethereum;
auto qshh = m_whisper;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, qeth, qshh, this));
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh));
});
connect(ui->webView, &QWebView::loadFinished, [=]()

1
third/MainWin.h

@ -132,6 +132,7 @@ private:
QNetworkAccessManager m_webCtrl;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr;
};

Loading…
Cancel
Save