Browse Source

Merge branch 'develop' into crypto

cl-refactor
subtly 10 years ago
parent
commit
6d87628557
  1. 18
      CodingStandards.txt
  2. 4
      eth/main.cpp
  3. 2
      libdevcore/Exceptions.h
  4. 16
      libethcore/Exceptions.h
  5. 15
      libethereum/Client.cpp
  6. 2
      libethereum/Client.h
  7. 2
      libevm/VM.h
  8. 2
      libp2p/Common.h
  9. 74
      libp2p/Host.cpp
  10. 6
      libp2p/Host.h
  11. 5
      libqethereum/QEthereum.cpp
  12. 5
      libqethereum/QEthereum.h
  13. 12
      libwebthree/WebThree.cpp
  14. 6
      libwebthree/WebThree.h
  15. 7
      test/CMakeLists.txt
  16. 152
      test/createRandomTest.cpp
  17. 29
      test/randomTestFiller.json
  18. 63
      test/vm.cpp
  19. 85
      test/vmArithmeticTestFiller.json
  20. 83
      test/vmIOandFlowOperationsTestFiller.json
  21. 100
      test/vmSystemOperationsTestFiller.json

18
CodingStandards.txt

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

4
eth/main.cpp

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

2
libdevcore/Exceptions.h

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

16
libethcore/Exceptions.h

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

15
libethereum/Client.cpp

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

2
libethereum/Client.h

@ -285,7 +285,7 @@ private:
State m_preMine; ///< The present state of the client.
State m_postMine; ///< The state of the client which we're mining (i.e. it'll have all the rewards added).
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::weak_ptr<EthereumHost> m_host; ///< Our Ethereum Host. Don't do anything if we can't lock.
std::vector<Miner> m_miners;
mutable boost::shared_mutex x_miners;

2
libevm/VM.h

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

2
libp2p/Common.h

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

74
libp2p/Host.cpp

@ -61,8 +61,9 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
Worker("p2p"),
m_clientVersion(_clientVersion),
m_netPrefs(_n),
m_acceptor(m_ioService),
m_socket(m_ioService),
m_ioService(new ba::io_service),
m_acceptor(*m_ioService),
m_socket(*m_ioService),
m_key(KeyPair::create())
{
populateAddresses();
@ -73,11 +74,15 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
Host::~Host()
{
stop();
quit();
}
void Host::start()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (isWorking())
stop();
@ -137,7 +142,18 @@ void Host::stop()
m_socket.close();
disconnectPeers();
if (!!m_ioService)
{
m_ioService->stop();
m_ioService->reset();
}
}
void Host::quit()
{
stop();
m_ioService.reset();
// m_acceptor & m_socket are DANGEROUS now.
}
unsigned Host::protocolVersion() const
@ -168,6 +184,10 @@ void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
void Host::disconnectPeers()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
for (unsigned n = 0;; n = 0)
{
{
@ -181,7 +201,7 @@ void Host::disconnectPeers()
}
if (!n)
break;
m_ioService.poll();
m_ioService->poll();
this_thread::sleep_for(chrono::milliseconds(100));
}
@ -204,6 +224,10 @@ void Host::seal(bytes& _b)
void Host::determinePublic(string const& _publicAddress, bool _upnp)
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (_upnp)
try
{
@ -211,7 +235,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
}
catch (NoUPnPDevice) {} // let m_upnp continue as null - we handle it properly.
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
if (m_upnp && m_upnp->isValid() && m_peerAddresses.size())
{
clog(NetNote) << "External addr:" << m_upnp->externalIP();
@ -249,6 +273,10 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp)
void Host::populateAddresses()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
#ifdef _WIN32
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
@ -289,7 +317,7 @@ void Host::populateAddresses()
if (getifaddrs(&ifaddr) == -1)
BOOST_THROW_EXCEPTION(NoNetworking());
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
for (ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next)
{
@ -422,6 +450,10 @@ Nodes Host::potentialPeers(RangeMask<unsigned> const& _known)
void Host::ensureAccepting()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
if (!m_accepting)
{
clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_public << ")";
@ -465,13 +497,17 @@ string Host::pocHost()
void Host::connect(std::string const& _addr, unsigned short _port) noexcept
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
for (int i = 0; i < 2; ++i)
{
try
{
if (i == 0)
{
bi::tcp::resolver r(m_ioService);
bi::tcp::resolver r(*m_ioService);
connect(r.resolve({_addr, toString(_port)})->endpoint());
}
else
@ -493,8 +529,12 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept
void Host::connect(bi::tcp::endpoint const& _ep)
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return;
clog(NetConnect) << "Attempting single-shot connection to " << _ep;
bi::tcp::socket* s = new bi::tcp::socket(m_ioService);
bi::tcp::socket* s = new bi::tcp::socket(*m_ioService);
s->async_connect(_ep, [=](boost::system::error_code const& ec)
{
if (ec)
@ -511,11 +551,15 @@ void Host::connect(bi::tcp::endpoint const& _ep)
void Node::connect(Host* _h)
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!_h->m_ioService)
return;
clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address << "from" << _h->id().abridged();
lastAttempted = std::chrono::system_clock::now();
failedAttempts++;
_h->m_ready -= index;
bi::tcp::socket* s = new bi::tcp::socket(_h->m_ioService);
bi::tcp::socket* s = new bi::tcp::socket(*_h->m_ioService);
s->async_connect(address, [=](boost::system::error_code const& ec)
{
if (ec)
@ -640,8 +684,12 @@ void Host::prunePeers()
i = m_peers.erase(i);
}
std::vector<PeerInfo> Host::peers(bool _updatePing) const
PeerInfos Host::peers(bool _updatePing) const
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (!m_ioService)
return PeerInfos();
RecursiveGuard l(x_peers);
if (_updatePing)
{
@ -658,6 +706,10 @@ std::vector<PeerInfo> Host::peers(bool _updatePing) const
void Host::doWork()
{
// if there's no ioService, it means we've had quit() called - bomb out - we're not allowed in here.
if (asserts(!!m_ioService))
return;
growPeers();
prunePeers();
@ -679,7 +731,7 @@ void Host::doWork()
pingAll();
}
m_ioService.poll();
m_ioService->poll();
}
void Host::pingAll()

6
libp2p/Host.h

@ -155,7 +155,7 @@ public:
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
/// Get peer information.
std::vector<PeerInfo> peers(bool _updatePing = false) const;
PeerInfos peers(bool _updatePing = false) const;
/// Get number of peers connected; equivalent to, but faster than, peers().size().
size_t peerCount() const { RecursiveGuard l(x_peers); return m_peers.size(); }
@ -180,6 +180,8 @@ public:
void stop();
bool isStarted() const { return isWorking(); }
void quit();
NodeId id() const { return m_key.pub(); }
void registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps);
@ -210,7 +212,7 @@ private:
static const int NetworkStopped = -1; ///< The value meaning we're not actually listening.
int m_listenPort = NetworkStopped; ///< What port are we listening on?
ba::io_service m_ioService; ///< IOService for network stuff.
std::unique_ptr<ba::io_service> m_ioService; ///< IOService for network stuff.
bi::tcp::acceptor m_acceptor; ///< Listening acceptor.
bi::tcp::socket m_socket; ///< Listening socket.

5
libqethereum/QEthereum.cpp

@ -111,11 +111,6 @@ QString QEthereum::sha3(QString _s1, QString _s2, QString _s3) const
return toQJS(dev::sha3(asBytes(padded(_s1, 32)) + asBytes(padded(_s2, 32)) + asBytes(padded(_s3, 32))));
}
QString QEthereum::sha3old(QString _s) const
{
return toQJS(dev::sha3(asBytes(_s)));
}
QString QEthereum::offset(QString _s, int _i) const
{
return toQJS(toU256(_s) + _i);

5
libqethereum/QEthereum.h

@ -123,13 +123,8 @@ public:
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); }

12
libwebthree/WebThree.cpp

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

6
libwebthree/WebThree.h

@ -122,10 +122,10 @@ public:
private:
std::string m_clientVersion; ///< Our end-application client's name/version.
std::unique_ptr<eth::Client> m_ethereum; ///< Main interface for Ethereum ("eth") protocol.
std::weak_ptr<shh::WhisperHost> m_whisper; ///< Main interface for Whisper ("shh") protocol.
p2p::Host m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
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.
};

7
test/CMakeLists.txt

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

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());
}
}

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"
}
}
}

63
test/vm.cpp

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

85
test/vmArithmeticTestFiller.json

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

83
test/vmIOandFlowOperationsTestFiller.json

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

100
test/vmSystemOperationsTestFiller.json

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

Loading…
Cancel
Save