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 0. Formatting
a. Use tabs for indentation! 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. - One indentation level -> exactly one byte (i.e. a tab character) in the source file.
b. Line widths: b. Line widths:
- Don't worry about having lines of code > 80-char wide. - 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. 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. f. No spaces when fewer than intra-expression three parens together; when three or more, space according to clarity.
g. No spaces for subscripting. g. No spaces for subscripting.
h. Space all other operators. h. No space before ':' but one after it, except in the ternary operator: one on both sides.
i. Braces, when used, always have their own lines and are at same indentation level as "parent" scope. i. Space all other operators.
j. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
(WRONG) (WRONG)
if( a==b[ i ] ) { printf ("Hello\n"); } 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. - 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. 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%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 +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. 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 ### Building

8
alethzero/MainWin.cpp

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

1
alethzero/MainWin.h

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

6
eth/main.cpp

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

15
exp/main.cpp

@ -29,12 +29,14 @@
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>
#include <libethereum/DownloadMan.h> #include <libethereum/DownloadMan.h>
#include <libwhisper/WhisperPeer.h> #include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::p2p; using namespace dev::p2p;
using namespace dev::shh; using namespace dev::shh;
#if 0
int main() int main()
{ {
DownloadMan man; DownloadMan man;
@ -69,8 +71,8 @@ int main()
cnote << i;*/ cnote << i;*/
return 0; return 0;
} }
#endif
/*
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
g_logVerbosity = 20; g_logVerbosity = 20;
@ -102,15 +104,16 @@ int main(int argc, char** argv)
ph.connect(remoteHost, remotePort); ph.connect(remoteHost, remotePort);
/// Only interested in the packet if the lowest bit is 1 /// 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) 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)) 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; return 0;
} }
*/

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
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 // error information to be added to exceptions
typedef boost::error_info<struct tag_invalidSymbol, char> errinfo_invalidSymbol; 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; 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([&]() m_work.reset(new thread([&]()
{ {
setThreadName(m_name.c_str()); setThreadName(m_name.c_str());
startedWorking();
while (!m_stop) while (!m_stop)
{ {
this_thread::sleep_for(chrono::milliseconds(30)); this_thread::sleep_for(chrono::milliseconds(30));

1
libdevcore/Worker.h

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

5
libdevcrypto/Common.cpp

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

2
libdevcrypto/CryptoHeaders.h

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

4
libdevcrypto/MemoryDB.cpp

@ -23,12 +23,9 @@
#include "MemoryDB.h" #include "MemoryDB.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
namespace dev namespace dev
{ {
namespace eth
{
std::map<h256, std::string> MemoryDB::get() const 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 dev
{ {
namespace eth
{
struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 18; }; 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" #include "OverlayDB.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
namespace dev namespace dev
{ {
namespace eth
{
OverlayDB::~OverlayDB() 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 dev
{ {
namespace eth
{
class OverlayDB: public MemoryDB class OverlayDB: public MemoryDB
{ {
@ -63,4 +61,3 @@ private:
}; };
} }
}

4
libdevcrypto/SHA3.cpp

@ -24,12 +24,9 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
namespace dev namespace dev
{ {
namespace eth
{
h256 EmptySHA3 = sha3(bytesConstRef()); 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 dev
{ {
namespace eth
{
// SHA-3 convenience routines. // SHA-3 convenience routines.
@ -69,4 +67,3 @@ void sha256(bytesConstRef _input, bytesRef _output);
void ripemd160(bytesConstRef _input, bytesRef _output); void ripemd160(bytesConstRef _input, bytesRef _output);
} }
}

3
libdevcrypto/TrieCommon.cpp

@ -23,8 +23,6 @@
namespace dev namespace dev
{ {
namespace eth
{
/* /*
* Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1 * 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 dev
{ {
namespace eth
{
inline byte nibble(bytesConstRef _data, unsigned _i) inline byte nibble(bytesConstRef _data, unsigned _i)
{ {
@ -49,10 +47,29 @@ struct NibbleSlice
NibbleSlice(bytesConstRef _d = bytesConstRef(), unsigned _o = 0): data(_d), offset(_o) {} NibbleSlice(bytesConstRef _d = bytesConstRef(), unsigned _o = 0): data(_d), offset(_o) {}
byte operator[](unsigned _index) const { return nibble(data, offset + _index); } byte operator[](unsigned _index) const { return nibble(data, offset + _index); }
unsigned size() const { return data.size() * 2 - offset; } unsigned size() const { return data.size() * 2 - offset; }
bool empty() const { return !size(); }
NibbleSlice mid(unsigned _index) const { return NibbleSlice(data, offset + _index); } 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(); } 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()); } 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 _k) const { return _k.size() == size() && shared(_k) == _k.size(); }
bool operator!=(NibbleSlice _s) const { return !operator==(_s); } 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" #include "TrieDB.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
#if !ETH_LANGUAGES #if !ETH_LANGUAGES
const h256 dev::eth::c_shaNull = sha3(rlp("")); const h256 dev::c_shaNull = sha3(rlp(""));
#endif #endif

164
libdevcrypto/TrieDB.h

@ -39,8 +39,6 @@ namespace ldb = leveldb;
namespace dev namespace dev
{ {
namespace eth
{
struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 17; }; struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 17; };
#define tdebug clog(TrieDBChannel) #define tdebug clog(TrieDBChannel)
@ -171,6 +169,7 @@ public:
iterator() {} iterator() {}
iterator(GenericTrieDB const* _db); iterator(GenericTrieDB const* _db);
iterator(GenericTrieDB const* _db, bytesConstRef _key);
iterator& operator++() { next(); return *this; } iterator& operator++() { next(); return *this; }
@ -184,13 +183,17 @@ public:
private: private:
void next(); void next();
void next(NibbleSlice _key);
struct Node struct Node
{ {
std::string rlp; std::string rlp;
std::string key; // as hexPrefixEncoding. 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 setFirstChild() { child = 16; }
void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); } void incrementChild() { child = child == 16 ? 0 : child == 15 ? 17 : (child + 1); }
@ -205,6 +208,8 @@ public:
iterator begin() const { return this; } iterator begin() const { return this; }
iterator end() const { return iterator(); } iterator end() const { return iterator(); }
iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); }
private: private:
RLPStream& streamNode(RLPStream& _s, bytes const& _b); RLPStream& streamNode(RLPStream& _s, bytes const& _b);
@ -298,6 +303,7 @@ public:
iterator() {} iterator() {}
iterator(TrieDB const* _db): Super(_db) {} 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(); }
value_type operator->() const { return at(); } value_type operator->() const { return at(); }
@ -307,6 +313,7 @@ public:
iterator begin() const { return this; } iterator begin() const { return this; }
iterator end() const { return iterator(); } 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> template <class KeyType, class DB>
@ -317,14 +324,11 @@ std::ostream& operator<<(std::ostream& _out, TrieDB<KeyType, DB> const& _db)
return _out; return _out;
} }
}
} }
// Template implementations... // Template implementations...
namespace dev namespace dev
{ {
namespace eth
{
template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _db) template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _db)
{ {
@ -333,6 +337,13 @@ template <class DB> GenericTrieDB<DB>::iterator::iterator(GenericTrieDB const* _
next(); 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 template <class DB> typename GenericTrieDB<DB>::iterator::value_type GenericTrieDB<DB>::iterator::at() const
{ {
assert(m_trail.size()); 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). assert(!(b.key[0] & 0x10)); // should be an integer number of bytes (i.e. not an odd number of nibbles).
RLP rlp(b.rlp); 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) 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 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() 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) void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
{ {
hash = dev::eth::sha3(_header.data()); hash = dev::sha3(_header.data());
int field = 0; int field = 0;
try try

2
libethcore/CommonEth.cpp

@ -100,7 +100,7 @@ Address toAddress(Secret _private)
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65); ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok) if (!ok)
return Address(); 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 #if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl; cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << _private << endl; cout << "SEC: " << _private << endl;

16
libethcore/Exceptions.h

@ -44,26 +44,26 @@ struct FeeTooSmall: virtual dev::Exception {};
struct TooMuchGasUsed: virtual dev::Exception {}; struct TooMuchGasUsed: virtual dev::Exception {};
struct ExtraDataTooBig: virtual dev::Exception {}; struct ExtraDataTooBig: virtual dev::Exception {};
struct InvalidSignature: 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 InvalidUnclesHash: virtual dev::Exception {};
struct InvalidUncle: virtual dev::Exception {}; struct InvalidUncle: virtual dev::Exception {};
struct UncleTooOld: 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 DuplicateUncleNonce: virtual dev::Exception {};
struct InvalidStateRoot: 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 InvalidTransaction: virtual dev::Exception {};
struct InvalidDifficulty: 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 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: 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 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 InvalidTransactionGasUsed: virtual dev::Exception {};
struct InvalidTransactionStateRoot: virtual dev::Exception {}; struct InvalidTransactionStateRoot: virtual dev::Exception {};
struct InvalidTimestamp: 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 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: 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 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 InvalidParentHash: virtual dev::Exception {};
struct InvalidNumber: 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 namespace dev
{ {
class OverlayDB;
namespace eth namespace eth
{ {
static const h256s NullH256s; static const h256s NullH256s;
class State; class State;
class OverlayDB;
struct AlreadyHaveBlock: virtual Exception {}; struct AlreadyHaveBlock: virtual Exception {};
struct UnknownParent: virtual Exception {}; struct UnknownParent: virtual Exception {};

15
libethereum/Client.cpp

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

5
libethereum/CommonNet.h

@ -30,6 +30,9 @@
namespace dev namespace dev
{ {
class OverlayDB;
namespace eth 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_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). static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
#endif #endif
class OverlayDB;
class BlockChain; class BlockChain;
class TransactionQueue; class TransactionQueue;
class EthereumHost; class EthereumHost;

5
libethereum/EthereumHost.cpp

@ -86,6 +86,11 @@ void EthereumHost::noteNeedsSyncing(EthereumPeer* _who)
void EthereumHost::changeSyncer(EthereumPeer* _syncer) void EthereumHost::changeSyncer(EthereumPeer* _syncer)
{ {
if (_syncer)
clog(NetAllDetail) << "Changing syncer to" << _syncer->session()->socketId();
else
clog(NetAllDetail) << "Clearing syncer.";
m_syncer = _syncer; m_syncer = _syncer;
if (isSyncing()) 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_man.resetToChain(m_syncingNeededBlocks);
host()->m_latestBlockSent = m_syncingLatestHash; host()->m_latestBlockSent = m_syncingLatestHash;
} }
else 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) 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. // 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); auto blocks = m_sub.nextFetch(c_maxBlocksAsk);
if (blocks.size()) if (blocks.size())
{ {

2
libethereum/MessageFilter.cpp

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

15
libethereum/State.cpp

@ -58,7 +58,7 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
int pubkeylen = 65; int pubkeylen = 65;
secp256k1_start(); secp256k1_start();
if (secp256k1_ecdsa_recover_compact(in.hash.data(), 32, in.r.data(), pubkey, &pubkeylen, 0, (int)(u256)in.v - 27)) 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))); 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 struct CachedAddressState
{ {
CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} 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 dev
{ {
namespace test { class FakeExtVM; class FakeState; } namespace test { class FakeExtVM; class FakeState; }
namespace eth namespace eth
@ -116,6 +117,8 @@ public:
/// @returns the set containing all addresses currently in use in Ethereum. /// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const; std::map<Address, u256> addresses() const;
Address nextActiveAddress(Address _a) const;
BlockInfo const& info() const { return m_currentBlock; } BlockInfo const& info() const { return m_currentBlock; }
/// @brief Checks that mining the current object will result in a valid block. /// @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()); BOOST_THROW_EXCEPTION(InvalidSignature());
// TODO: check right160 is correct and shouldn't be left160. // 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 #if ETH_ADDRESS_DEBUG
cout << "---- RECOVER -------------------------------" << endl; cout << "---- RECOVER -------------------------------" << endl;

4
libethereum/Transaction.h

@ -67,8 +67,8 @@ struct Transaction
void fillStream(RLPStream& _s, bool _sig = true) const; void fillStream(RLPStream& _s, bool _sig = true) const;
bytes rlp(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return s.out(); } 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)); } 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()); } 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::eth::sha3Bytes(s.out()); } bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return dev::sha3Bytes(s.out()); }
private: private:
mutable Address m_sender; mutable Address m_sender;

2
libevm/VM.h

@ -41,7 +41,7 @@ struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {}; struct BadInstruction: virtual VMException {};
struct BadJumpDestination: virtual VMException {}; struct BadJumpDestination: virtual VMException {};
struct OutOfGas: 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. // 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. // 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; 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"), Worker("p2p"),
m_clientVersion(_clientVersion), m_clientVersion(_clientVersion),
m_netPrefs(_n), m_netPrefs(_n),
m_acceptor(m_ioService), m_ioService(new ba::io_service),
m_socket(m_ioService), m_acceptor(*m_ioService),
m_socket(*m_ioService),
m_key(KeyPair::create()) m_key(KeyPair::create())
{ {
populateAddresses(); populateAddresses();
@ -73,11 +74,15 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
Host::~Host() Host::~Host()
{ {
stop(); quit();
} }
void Host::start() 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()) if (isWorking())
stop(); 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) for (auto const& h: m_capabilities)
h.second->onStarting(); h.second->onStarting();
@ -137,7 +134,18 @@ void Host::stop()
m_socket.close(); m_socket.close();
disconnectPeers(); disconnectPeers();
if (!!m_ioService)
{
m_ioService->stop();
m_ioService->reset();
}
}
void Host::quit()
{
stop();
m_ioService.reset(); m_ioService.reset();
// m_acceptor & m_socket are DANGEROUS now.
} }
unsigned Host::protocolVersion() const unsigned Host::protocolVersion() const
@ -168,6 +176,10 @@ void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
void Host::disconnectPeers() 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) for (unsigned n = 0;; n = 0)
{ {
{ {
@ -181,7 +193,7 @@ void Host::disconnectPeers()
} }
if (!n) if (!n)
break; break;
m_ioService.poll(); m_ioService->poll();
this_thread::sleep_for(chrono::milliseconds(100)); this_thread::sleep_for(chrono::milliseconds(100));
} }
@ -204,6 +216,10 @@ void Host::seal(bytes& _b)
void Host::determinePublic(string const& _publicAddress, bool _upnp) 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) if (_upnp)
try 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. 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()) if (m_upnp && m_upnp->isValid() && m_peerAddresses.size())
{ {
clog(NetNote) << "External addr:" << m_upnp->externalIP(); clog(NetNote) << "External addr:" << m_upnp->externalIP();
@ -249,6 +265,10 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
void Host::populateAddresses() 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 #ifdef _WIN32
WSAData wsaData; WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
@ -289,7 +309,7 @@ void Host::populateAddresses()
if (getifaddrs(&ifaddr) == -1) if (getifaddrs(&ifaddr) == -1)
BOOST_THROW_EXCEPTION(NoNetworking()); 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) 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) if (_a.port() < 30300 && _a.port() > 30303)
cwarn << "Wierd port being recorded!"; cwarn << "Wierd port being recorded!";
if (_a.port() >= 49152) if (_a.port() >= /*49152*/32768)
{ {
cwarn << "Private port being recorded - setting to 0"; cwarn << "Private port being recorded - setting to 0";
_a = bi::tcp::endpoint(_a.address(), 0); _a = bi::tcp::endpoint(_a.address(), 0);
@ -422,6 +442,10 @@ Nodes Host::potentialPeers(RangeMask<unsigned> const& _known)
void Host::ensureAccepting() 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) if (!m_accepting)
{ {
clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")"; 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 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) for (int i = 0; i < 2; ++i)
{ {
try try
{ {
if (i == 0) if (i == 0)
{ {
bi::tcp::resolver r(m_ioService); bi::tcp::resolver r(*m_ioService);
connect(r.resolve({_addr, toString(_port)})->endpoint()); connect(r.resolve({_addr, toString(_port)})->endpoint());
} }
else else
@ -493,8 +521,12 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept
void Host::connect(bi::tcp::endpoint const& _ep) 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; 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) s->async_connect(_ep, [=](boost::system::error_code const& ec)
{ {
if (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(); // if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
lastAttempted = std::chrono::system_clock::now(); if (!m_ioService)
failedAttempts++; return;
_h->m_ready -= index;
bi::tcp::socket* s = new bi::tcp::socket(_h->m_ioService); clog(NetConnect) << "Attempting connection to node" << _n->id.abridged() << "@" << _n->address << "from" << id().abridged();
s->async_connect(address, [=](boost::system::error_code const& ec) _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) if (ec)
{ {
clog(NetConnect) << "Connection refused to node" << id.abridged() << "@" << address << "(" << ec.message() << ")"; clog(NetConnect) << "Connection refused to node" << _n->id.abridged() << "@" << _n->address << "(" << ec.message() << ")";
lastDisconnect = TCPError; _n->lastDisconnect = TCPError;
lastAttempted = std::chrono::system_clock::now(); _n->lastAttempted = std::chrono::system_clock::now();
_h->m_ready += index; m_ready += _n->index;
} }
else else
{ {
clog(NetConnect) << "Connected to" << id.abridged() << "@" << address; clog(NetConnect) << "Connected to" << _n->id.abridged() << "@" << _n->address;
lastConnected = std::chrono::system_clock::now(); _n->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. 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(); p->start();
} }
delete s; delete s;
@ -594,7 +630,7 @@ void Host::growPeers()
if (ns.size()) if (ns.size())
for (Node const& i: ns) for (Node const& i: ns)
{ {
m_nodes[i.id]->connect(this); connect(m_nodes[i.id]);
if (!--morePeers) if (!--morePeers)
return; return;
} }
@ -640,8 +676,12 @@ void Host::prunePeers()
i = m_peers.erase(i); 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); RecursiveGuard l(x_peers);
if (_updatePing) if (_updatePing)
{ {
@ -656,8 +696,23 @@ std::vector<PeerInfo> Host::peers(bool _updatePing) const
return ret; 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() 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(); growPeers();
prunePeers(); prunePeers();
@ -679,7 +734,7 @@ void Host::doWork()
pingAll(); pingAll();
} }
m_ioService.poll(); m_ioService->poll();
} }
void Host::pingAll() void Host::pingAll()
@ -701,7 +756,7 @@ bytes Host::saveNodes() const
{ {
Node const& n = *(i.second); Node const& n = *(i.second);
// TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 && // 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); nodes.appendList(10);
if (n.address.address().is_v4()) if (n.address.address().is_v4())

13
libp2p/Host.h

@ -97,8 +97,6 @@ struct Node
else else
return score < _n.score; return score < _n.score;
} }
void connect(Host* _h);
}; };
using Nodes = std::vector<Node>; using Nodes = std::vector<Node>;
@ -147,6 +145,7 @@ public:
static std::string pocHost(); static std::string pocHost();
void connect(std::string const& _addr, unsigned short _port = 30303) noexcept; void connect(std::string const& _addr, unsigned short _port = 30303) noexcept;
void connect(bi::tcp::endpoint const& _ep); 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. /// @returns true iff we have the a peer of the given id.
bool havePeer(NodeId _id) const; bool havePeer(NodeId _id) const;
@ -155,7 +154,7 @@ public:
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; } void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
/// Get peer information. /// 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(). /// Get number of peers connected; equivalent to, but faster than, peers().size().
size_t peerCount() const { RecursiveGuard l(x_peers); return m_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; } 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 start();
void stop(); void stop();
bool isStarted() const { return isWorking(); } bool isStarted() const { return isWorking(); }
void quit();
NodeId id() const { return m_key.pub(); } NodeId id() const { return m_key.pub(); }
void registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps); void registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps);
@ -195,6 +196,8 @@ private:
void growPeers(); void growPeers();
void prunePeers(); void prunePeers();
virtual void startedWorking();
/// Conduct I/O, polling, syncing, whatever. /// 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. /// 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. /// 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. static const int NetworkStopped = -1; ///< The value meaning we're not actually listening.
int m_listenPort = NetworkStopped; ///< What port are we listening on? 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::acceptor m_acceptor; ///< Listening acceptor.
bi::tcp::socket m_socket; ///< Listening socket. bi::tcp::socket m_socket; ///< Listening socket.

4
libp2p/Session.cpp

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

2
libp2p/UPnP.h

@ -25,6 +25,7 @@
#include <set> #include <set>
#include <string> #include <string>
#include <memory> #include <memory>
#include <thread>
struct UPNPUrls; struct UPNPUrls;
struct IGDdatas; struct IGDdatas;
@ -46,6 +47,7 @@ public:
bool isValid() const { return m_ok; } bool isValid() const { return m_ok; }
private:
std::set<int> m_reg; std::set<int> m_reg;
bool m_ok; bool m_ok;
std::shared_ptr<struct UPNPUrls> m_urls; 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): 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 // required to prevent crash on osx when performing addto/evaluatejavascript calls
moveToThread(_p->thread()); moveToThread(_p->thread());
setAccounts(_accounts);
} }
QEthereum::~QEthereum() QEthereum::~QEthereum()
@ -81,11 +82,6 @@ void QEthereum::clearWatches()
m_watches.clear(); m_watches.clear();
} }
QString QEthereum::secretToAddress(QString _s) const
{
return toQJS(KeyPair(toSecret(_s)).address());
}
eth::Interface* QEthereum::client() const eth::Interface* QEthereum::client() const
{ {
return m_client; return m_client;
@ -96,27 +92,22 @@ QString QEthereum::lll(QString _s) const
return toQJS(dev::eth::compileLLL(_s.toStdString())); return toQJS(dev::eth::compileLLL(_s.toStdString()));
} }
QString QEthereum::sha3(QString _s) const QString QDev::sha3(QString _s) const
{
return toQJS(dev::eth::sha3(toBytes(_s)));
}
QString QEthereum::sha3(QString _s1, QString _s2) 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); return toQJS(toU256(_s) + _i);
} }
@ -131,33 +122,11 @@ QString QEthereum::number() const
return m_client ? QString::number(client()->number() + 1) : ""; 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 QEthereum::accounts() const
{ {
QStringList ret; QStringList ret;
for (auto i: m_accounts) for (auto i: m_accounts)
ret.push_back(toQJS(i.address())); ret.push_back(toQJS(i.first));
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()));
return ret; return ret;
} }
@ -269,7 +238,7 @@ static dev::eth::MessageFilter toMessageFilter(QString _json)
struct TransactionSkeleton struct TransactionSkeleton
{ {
Secret from; Address from;
Address to; Address to;
u256 value; u256 value;
bytes data; bytes data;
@ -283,7 +252,7 @@ static TransactionSkeleton toTransaction(QString _json)
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("from")) if (f.contains("from"))
ret.from = toSecret(f["from"].toString()); ret.from = toAddress(f["from"].toString());
if (f.contains("to")) if (f.contains("to"))
ret.to = toAddress(f["to"].toString()); ret.to = toAddress(f["to"].toString());
if (f.contains("value")) if (f.contains("value"))
@ -458,26 +427,17 @@ void QEthereum::setListening(bool)
client()->stopNetwork();*/ 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) unsigned QEthereum::peerCount() const
{
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)
{ {
if (!m_client) return /*m_client ? (unsigned)client()->peerCount() :*/ 0;
return;
client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice));
client()->flushTransactions();
} }
QString QEthereum::doTransact(QString _json) QString QEthereum::doTransact(QString _json)
@ -488,18 +448,23 @@ QString QEthereum::doTransact(QString _json)
TransactionSkeleton t = toTransaction(_json); TransactionSkeleton t = toTransaction(_json);
if (!t.from && m_accounts.size()) if (!t.from && m_accounts.size())
{ {
auto b = m_accounts.first(); auto b = m_accounts.begin()->first;
for (auto a: m_accounts) for (auto a: m_accounts)
if (client()->balanceAt(KeyPair(a).address()) > client()->balanceAt(KeyPair(b).address())) if (client()->balanceAt(a.first) > client()->balanceAt(b))
b = a; b = a.first;
t.from = b.secret(); t.from = b;
} }
if (!m_accounts.count(t.from))
return QString();
if (!t.gasPrice) if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas) 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) 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 else
ret = toQJS(client()->transact(t.from, t.value, t.data, t.gas, t.gasPrice)); ret = toQJS(client()->transact(t.from, t.value, t.data, t.gas, t.gasPrice));
client()->flushTransactions(); client()->flushTransactions();
@ -511,15 +476,21 @@ QString QEthereum::doCall(QString _json)
if (!m_client) if (!m_client)
return QString(); return QString();
TransactionSkeleton t = toTransaction(_json); TransactionSkeleton t = toTransaction(_json);
if (!t.to)
return QString();
if (!t.from && m_accounts.size()) 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) if (!t.gasPrice)
t.gasPrice = 10 * dev::eth::szabo; t.gasPrice = 10 * dev::eth::szabo;
if (!t.gas) if (!t.gas)
t.gas = client()->balanceAt(KeyPair(t.from).address()) / t.gasPrice; t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice);
bytes out = client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice); bytes out = client()->call(m_accounts[t.from].secret(), t.value, t.to, t.data, t.gas, t.gasPrice);
return asQString(out); 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); 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 class QEthereum: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -112,31 +133,12 @@ public:
/// Call when the client() is going to be deleted to make this object useless but safe. /// Call when the client() is going to be deleted to make this object useless but safe.
void clientDieing(); 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 QEthereum* self() { return this; }
Q_INVOKABLE QString secretToAddress(QString _s) const;
Q_INVOKABLE QString lll(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. // [NEW API] - Use this instead.
Q_INVOKABLE QString/*dev::u256*/ balanceAt(QString/*dev::Address*/ _a, int _block) const; Q_INVOKABLE QString/*dev::u256*/ balanceAt(QString/*dev::Address*/ _a, int _block) const;
Q_INVOKABLE double countAt(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/*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 doTransact(QString _json);
Q_INVOKABLE QString doCall(QString _json); Q_INVOKABLE QString doCall(QString _json);
@ -172,9 +172,6 @@ public:
QString/*dev::u256*/ number() const; QString/*dev::u256*/ number() const;
int getDefault() 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; QStringList/*list of dev::Address*/ accounts() const;
unsigned peerCount() const; unsigned peerCount() const;
@ -200,8 +197,7 @@ private:
Q_PROPERTY(QString number READ number NOTIFY watchChanged) Q_PROPERTY(QString number READ number NOTIFY watchChanged)
Q_PROPERTY(QString coinbase READ coinbase WRITE setCoinbase NOTIFY coinbaseChanged) Q_PROPERTY(QString coinbase READ coinbase WRITE setCoinbase NOTIFY coinbaseChanged)
Q_PROPERTY(QString gasPrice READ gasPrice) Q_PROPERTY(QString gasPrice READ gasPrice)
Q_PROPERTY(QString key READ key NOTIFY keysChanged) Q_PROPERTY(QStringList accounts READ accounts NOTIFY keysChanged)
Q_PROPERTY(QStringList keys READ keys NOTIFY keysChanged)
Q_PROPERTY(bool mining READ isMining WRITE setMining NOTIFY netChanged) Q_PROPERTY(bool mining READ isMining WRITE setMining NOTIFY netChanged)
Q_PROPERTY(bool listening READ isListening WRITE setListening NOTIFY netChanged) Q_PROPERTY(bool listening READ isListening WRITE setListening NOTIFY netChanged)
Q_PROPERTY(unsigned peerCount READ peerCount NOTIFY miningChanged) Q_PROPERTY(unsigned peerCount READ peerCount NOTIFY miningChanged)
@ -209,7 +205,7 @@ private:
dev::eth::Interface* m_client; dev::eth::Interface* m_client;
std::vector<unsigned> m_watches; std::vector<unsigned> m_watches;
QList<dev::KeyPair> m_accounts; std::map<dev::Address, dev::KeyPair> m_accounts;
}; };
class QWhisper: public QObject class QWhisper: public QObject
@ -251,22 +247,30 @@ private:
std::vector<unsigned> m_watches; 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("shh", _shh, QWebFrame::ScriptOwnership); \
frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \ _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->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \ _frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \
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)) }"); \
} }
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) 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() 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() std::vector<PeerInfo> WebThreeDirect::peers()

6
libwebthree/WebThree.h

@ -106,7 +106,7 @@ public:
bool haveNetwork() const { return m_net.isStarted(); } 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(); } p2p::NodeId id() const { return m_net.id(); }
@ -122,10 +122,10 @@ public:
private: private:
std::string m_clientVersion; ///< Our end-application client's name/version. 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::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. 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 PacketCount
}; };
using Topic = h256;
} }
} }

11
libwhisper/Interface.cpp

@ -36,15 +36,8 @@ using namespace dev::shh;
bool MessageFilter::matches(Message const& _m) const bool MessageFilter::matches(Message const& _m) const
{ {
for (auto const& t: m_topicMasks) for (TopicMask const& t: m_topicMasks)
{ if (((t.first ^ _m.topic) & t.second) == 0)
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;
return true; return true;
NEXT:;
}
return false; return false;
} }

19
libwhisper/Interface.h

@ -37,20 +37,29 @@ namespace dev
namespace shh namespace shh
{ {
/*struct TopicMask
{
Topic data;
Topic mask;
};*/
using TopicMask = std::pair<Topic, Topic>;
using TopicMasks = std::vector<TopicMask>;
class MessageFilter class MessageFilter
{ {
public: public:
MessageFilter() {} MessageFilter() {}
MessageFilter(std::vector<std::pair<bytes, bytes> > const& _m): m_topicMasks(_m) {} MessageFilter(TopicMasks const& _m): m_topicMasks(_m) {}
MessageFilter(RLP const& _r): m_topicMasks((std::vector<std::pair<bytes, bytes>>)_r) {} MessageFilter(RLP const& _r): m_topicMasks((TopicMasks)_r) {}
void fillStream(RLPStream& _s) const { _s << m_topicMasks; } 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; bool matches(Message const& _m) const;
private: private:
std::vector<std::pair<bytes, bytes> > m_topicMasks; TopicMasks m_topicMasks;
}; };
struct InstalledFilter struct InstalledFilter
@ -85,7 +94,7 @@ public:
virtual Message message(h256 _m) const = 0; 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; }; 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 expiry = 0;
unsigned ttl = 0; unsigned ttl = 0;
bytes topic; // TODO: change to h256 Topic topic; // TODO: change to h256
bytes payload; bytes payload;
Message() {} 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) Message(RLP const& _m)
{ {
expiry = _m[0].toInt<unsigned>(); expiry = _m[0].toInt<unsigned>();
ttl = _m[1].toInt<unsigned>(); ttl = _m[1].toInt<unsigned>();
topic = _m[2].toBytes(); topic = (Topic)_m[2];
payload = _m[3].toBytes(); payload = _m[3].toBytes();
} }
operator bool () const { return !!expiry; } operator bool () const { return !!expiry; }
void streamOut(RLPStream& _s) const { _s.appendList(4) << expiry << ttl << topic << payload; } 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 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: private:
void streamMessage(h256 _m, RLPStream& _s) const; 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; cnote << "Saved" << rechex << "to" << outFile;
} }
catch (dev::eth::InvalidTrie const& _e) catch (dev::InvalidTrie const& _e)
{ {
cwarn << "Corrupted trie.\n" << diagnostic_information(_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) cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp")
include_directories(..) include_directories(..)
link_directories(../libethcore) link_directories(../libethcore)
@ -8,6 +9,7 @@ link_directories(../libethereum)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
add_executable(testeth ${SRC_LIST} ${HEADERS}) add_executable(testeth ${SRC_LIST} ${HEADERS})
add_executable(createRandomTest createRandomTest.cpp vm.cpp)
target_link_libraries(testeth ethereum) target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore) target_link_libraries(testeth ethcore)
@ -15,6 +17,11 @@ target_link_libraries(testeth secp256k1)
target_link_libraries(testeth gmp) target_link_libraries(testeth gmp)
target_link_libraries(testeth ${CRYPTOPP_LS}) 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") if ("${TARGET_PLATFORM}" STREQUAL "w64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
target_link_libraries(testeth boost_system-mt-s) target_link_libraries(testeth boost_system-mt-s)

4
test/MemTrie.cpp

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

11
test/TestHelperCrypto.h

@ -22,11 +22,22 @@
#pragma once #pragma once
//#include <ostream> //#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 <eccrypto.h>
#include <ecp.h> #include <ecp.h>
#include <files.h> #include <files.h>
#include <osrng.h> #include <osrng.h>
#include <oids.h> #include <oids.h>
#pragma warning(pop)
#pragma GCC diagnostic pop
using namespace std; using namespace std;
using namespace CryptoPP; 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); 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); pubkey.resize(pubkeylen);
cout << "RECPUB: " << dec << ret << " " << pubkeylen << " " << toHex(pubkey) << endl; 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 #endif
return 0; return 0;

1
test/hexPrefix.cpp

@ -29,7 +29,6 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
namespace js = json_spirit; namespace js = json_spirit;
BOOST_AUTO_TEST_CASE(hexPrefix_test) 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 ) if ( v.type() == js::str_type )
{ {
const std::string& expectedText = v.get_str(); const std::string& expectedText = v.get_str();
if ( expectedText.front() == '#' ) if ( !expectedText.empty() && expectedText.front() == '#' )
{ {
// Deal with bigint instead of a raw string // Deal with bigint instead of a raw string
std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); std::string bigIntStr = expectedText.substr(1,expectedText.length()-1);

46
test/trie.cpp

@ -31,7 +31,6 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth;
namespace js = json_spirit; 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) BOOST_AUTO_TEST_CASE(trieStess)
{ {
cnote << "Stress-testing Trie..."; cnote << "Stress-testing Trie...";

74
test/vm.cpp

@ -22,6 +22,7 @@
#include "vm.h" #include "vm.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <boost/filesystem/path.hpp>
#define FILL_TESTS #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 << "not able to call to : " << myAddress << "\n";
cnote << "in FakeExtVM you can only make a call to " << na << "\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; 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 << "not able to call to : " << (_codeAddressOverride ? _codeAddressOverride : _receiveAddress) << "\n";
cnote << "in FakeExtVM you can only make a call to " << na << "\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; return false;
} }
} }
@ -251,12 +252,13 @@ mObject FakeExtVM::exportEnv()
void FakeExtVM::importEnv(mObject& _o) void FakeExtVM::importEnv(mObject& _o)
{ {
BOOST_REQUIRE(_o.count("previousHash") > 0); // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
BOOST_REQUIRE(_o.count("currentGasLimit") > 0); assert(_o.count("previousHash") > 0);
BOOST_REQUIRE(_o.count("currentDifficulty") > 0); assert(_o.count("currentGasLimit") > 0);
BOOST_REQUIRE(_o.count("currentTimestamp") > 0); assert(_o.count("currentDifficulty") > 0);
BOOST_REQUIRE(_o.count("currentCoinbase") > 0); assert(_o.count("currentTimestamp") > 0);
BOOST_REQUIRE(_o.count("currentNumber") > 0); assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0);
previousBlock.hash = h256(_o["previousHash"].get_str()); previousBlock.hash = h256(_o["previousHash"].get_str());
currentBlock.number = toInt(_o["currentNumber"]); currentBlock.number = toInt(_o["currentNumber"]);
@ -293,10 +295,11 @@ void FakeExtVM::importState(mObject& _object)
for (auto const& i: _object) for (auto const& i: _object)
{ {
mObject o = i.second.get_obj(); mObject o = i.second.get_obj();
BOOST_REQUIRE(o.count("balance") > 0); // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
BOOST_REQUIRE(o.count("nonce") > 0); assert(o.count("balance") > 0);
BOOST_REQUIRE(o.count("storage") > 0); assert(o.count("nonce") > 0);
BOOST_REQUIRE(o.count("code") > 0); assert(o.count("storage") > 0);
assert(o.count("code") > 0);
auto& a = addresses[Address(i.first)]; auto& a = addresses[Address(i.first)];
get<0>(a) = toInt(o["balance"]); get<0>(a) = toInt(o["balance"]);
@ -334,13 +337,14 @@ mObject FakeExtVM::exportExec()
void FakeExtVM::importExec(mObject& _o) void FakeExtVM::importExec(mObject& _o)
{ {
BOOST_REQUIRE(_o.count("address")> 0); // cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
BOOST_REQUIRE(_o.count("caller") > 0); assert(_o.count("address")> 0);
BOOST_REQUIRE(_o.count("origin") > 0); assert(_o.count("caller") > 0);
BOOST_REQUIRE(_o.count("value") > 0); assert(_o.count("origin") > 0);
BOOST_REQUIRE(_o.count("data") > 0); assert(_o.count("value") > 0);
BOOST_REQUIRE(_o.count("gasPrice") > 0); assert(_o.count("data") > 0);
BOOST_REQUIRE(_o.count("gas") > 0); assert(_o.count("gasPrice") > 0);
assert(_o.count("gas") > 0);
myAddress = Address(_o["address"].get_str()); myAddress = Address(_o["address"].get_str());
caller = Address(_o["caller"].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("pre") > 0);
BOOST_REQUIRE(o.count("exec") > 0); BOOST_REQUIRE(o.count("exec") > 0);
VM vm;
dev::test::FakeExtVM fev; dev::test::FakeExtVM fev;
fev.importEnv(o["env"].get_obj()); fev.importEnv(o["env"].get_obj());
fev.importState(o["pre"].get_obj()); fev.importState(o["pre"].get_obj());
@ -508,11 +511,13 @@ void doTests(json_spirit::mValue& v, bool _fillin)
fev.code = &fev.thisTxCode; fev.code = &fev.thisTxCode;
} }
vm.reset(fev.gas);
bytes output; bytes output;
u256 gas;
try 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) catch (Exception const& _e)
{ {
@ -549,7 +554,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
o["post"] = mValue(fev.exportState()); o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates(); o["callcreates"] = fev.exportCallCreates();
o["out"] = "0x" + toHex(output); o["out"] = "0x" + toHex(output);
fev.push(o, "gas", vm.gas()); fev.push(o, "gas", gas);
} }
else else
{ {
@ -573,7 +578,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
else else
BOOST_CHECK(output == fromHex(o["out"].get_str())); 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.addresses == fev.addresses);
BOOST_CHECK(test.callcreates == fev.callcreates); BOOST_CHECK(test.callcreates == fev.callcreates);
} }
@ -610,16 +615,29 @@ void doTests(json_spirit::mValue& v, bool _fillin)
void executeTests(const string& _name) 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 #ifdef FILL_TESTS
try try
{ {
cnote << "Populating VM tests..."; cnote << "Populating VM tests...";
json_spirit::mValue v; 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."); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + "Filler.json is empty.");
json_spirit::read_string(s, v); json_spirit::read_string(s, v);
dev::test::doTests(v, true); 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) catch (Exception const& _e)
{ {
@ -635,8 +653,8 @@ void executeTests(const string& _name)
{ {
cnote << "Testing VM..." << _name; cnote << "Testing VM..." << _name;
json_spirit::mValue v; json_spirit::mValue v;
string s = asString(contents("../../../tests/vmtests/" + _name + ".json")); 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?"); 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); json_spirit::read_string(s, v);
dev::test::doTests(v, false); 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": { "sub0": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

83
test/vmIOandFlowOperationsTestFiller.json

@ -530,6 +530,61 @@
"gas" : "10000" "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": { "jumpi0": {
"env" : { "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": { "jumpi1": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

100
test/vmSystemOperationsTestFiller.json

@ -129,7 +129,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "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": { "CallToNameRegistratorOutOfGas": {
"env" : { "env" : {
@ -274,7 +310,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -310,7 +346,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -346,7 +382,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -382,7 +418,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -419,7 +455,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -455,7 +491,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -525,7 +561,7 @@
}, },
"cd1722f3947def4cf144679da39c4c32bdc35681" : { "cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -561,7 +597,7 @@
}, },
"cd1722f3947def4cf144679da39c4c32bdc35681" : { "cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -597,7 +633,7 @@
}, },
"cd1722f3947def4cf144679da39c4c32bdc35681" : { "cd1722f3947def4cf144679da39c4c32bdc35681" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -723,7 +759,7 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "balance" : "23",
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"nonce" : "0", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -759,7 +795,43 @@
}, },
"945304eb96065b2a98b57a48a06ae28d285a71b5" : { "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
"balance" : "23", "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", "nonce" : "0",
"storage" : { "storage" : {
} }
@ -790,7 +862,7 @@
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000", "balance" : "1000000000000000000",
"nonce" : 0, "nonce" : 0,
"code" : "0x600035560f6009590060203560003557", "code" : "0x600035560f600a59005d60203560003557",
"storage": {} "storage": {}
} }
}, },
@ -841,7 +913,7 @@
} }
}, },
"ABAcalls0": { "ABAcalls1": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0", "currentNumber" : "0",

4
third/MainWin.cpp

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

1
third/MainWin.h

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

Loading…
Cancel
Save