Browse Source

Merge branch 'develop' into quickgui

cl-refactor
Gav Wood 11 years ago
parent
commit
44c4c13a9b
  1. 20
      README.md
  2. 4
      alethzero/MainWin.cpp
  3. 5
      json_spirit/json_spirit_writer_template.h
  4. 4
      libethereum/BlockChain.cpp
  5. 6
      libethereum/BlockChain.h
  6. 45
      libethereum/Common.h
  7. 177
      libethereum/Instruction.cpp
  8. 26
      libethereum/PeerNetwork.cpp
  9. 8
      libethereum/TrieDB.h
  10. 19
      libethereum/VM.h
  11. 14
      release.sh
  12. 1
      test/crypto.cpp
  13. 1
      test/dagger.cpp
  14. 69
      test/hexPrefix.cpp
  15. 18
      test/main.cpp
  16. 90
      test/rlp.cpp
  17. 2
      test/state.cpp
  18. 54
      test/trie.cpp
  19. 81
      test/vm.cpp
  20. 82
      test/vmtests.json
  21. 15
      windows/bootstrap.sh

20
README.md

@ -1,21 +1,27 @@
# cpp-ethereum
## Ethereum C++ Client.
Ethereum C++ Client.
By Gav Wood, 2014.
Gav Wood, 2014.
Based on a design by Vitalik Buterin.
## Building
Contributors, builders and testers include Eric Lombrozo (cross-compilation), Tim Hughes (MSVC compilation & Dagger testing), Alex Leverington (Clang & Mac building), Marko Simovic (CI) and several others.
### Building
See https://github.com/ethereum/cpp-ethereum/wiki/Building and https://github.com/ethereum/cpp-ethereum/wiki/Compatibility-Info-and-Build-Tips .
## Yet To Do
### Testing
To run the tests, make sure you clone the tests repository from github.com/ethereum to tests is a sibling to cpp-ethereum-build.
### Yet To Do
See TODO
## License
### License
See LICENSE
## Contributing
### Contributing
Please read CodingStandards.txt thoroughly before making alterations to the code base. Please do *NOT* use an editor that automatically reformats whitespace away from astylerc or the formating guidelines as describled in CodingStandards.txt.

4
alethzero/MainWin.cpp

@ -122,7 +122,7 @@ Main::Main(QWidget *parent) :
{
m_servers = QString::fromUtf8(_r->readAll()).split("\n", QString::SkipEmptyParts);
});
QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc3.txt"));
QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc" + QString(ADD_QUOTES(ETH_VERSION)).section('.', 1, 1) + ".txt"));
r.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1712.0 Safari/537.36");
m_webCtrl.get(r);
srand(time(0));
@ -181,7 +181,7 @@ Address Main::fromString(QString const& _a) const
void Main::on_about_triggered()
{
QMessageBox::about(this, "About AlethZero PoC-3", "AlethZero/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM) "\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nTeam Ethereum++ includes: Eric Lombrozo, Marko Simovic, Alex Leverington, Tim Hughes and several others.");
QMessageBox::about(this, "About AlethZero PoC-" + QString(ADD_QUOTES(ETH_VERSION)).section('.', 1, 1), "AlethZero/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM) "\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nTeam Ethereum++ includes: Eric Lombrozo, Marko Simovic, Alex Leverington, Tim Hughes and several others.");
}
void Main::writeSettings()

5
json_spirit/json_spirit_writer_template.h

@ -25,7 +25,9 @@ namespace json_spirit
return 'A' - 10 + ch;
}
template< class String_type >
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs")
template< class String_type >
String_type non_printable_to_string( unsigned int c )
{
typedef typename String_type::value_type Char_type;
@ -41,6 +43,7 @@ namespace json_spirit
return result;
}
#pragma GCC diagnostic pop
template< typename Char_type, class String_type >
bool add_esc_char( Char_type c, String_type& s )

4
libethereum/BlockChain.cpp

@ -271,7 +271,7 @@ bytesConstRef BlockChain::block(h256 _hash) const
BlockDetails const& BlockChain::details(h256 _h) const
{
std::map<h256, BlockDetails>::const_iterator it;
BlockDetailsHash::const_iterator it;
bool fetchRequired;
{
lock_guard<mutex> l(m_lock);
@ -290,7 +290,7 @@ BlockDetails const& BlockChain::details(h256 _h) const
{
lock_guard<mutex> l(m_lock);
bool ok;
tie(it, ok) = m_details.insert(make_pair(_h, BlockDetails(RLP(s))));
tie(it, ok) = m_details.insert(std::make_pair(_h, BlockDetails(RLP(s))));
}
}
return it->second;

6
libethereum/BlockChain.h

@ -48,6 +48,8 @@ struct BlockDetails
h256s children;
};
typedef std::map<h256, BlockDetails> BlockDetailsHash;
static const BlockDetails NullBlockDetails;
static const h256s NullH256s;
@ -72,7 +74,7 @@ public:
/// (Potentially) renders invalid existing bytesConstRef returned by lastBlock.
/// To be called from main loop every 100ms or so.
void process();
/// Attempt to import the given block.
bool attemptImport(bytes const& _block, Overlay const& _stateDB);
@ -101,7 +103,7 @@ private:
void checkConsistency();
/// Get fully populated from disk DB.
mutable std::map<h256, BlockDetails> m_details;
mutable BlockDetailsHash m_details;
mutable std::map<h256, std::string> m_cache;
mutable std::mutex m_lock;

45
libethereum/Common.h

@ -24,7 +24,7 @@
#pragma once
// define version
#define ETH_VERSION 0.3.7
#define ETH_VERSION 0.4.0
// way to many uint to size_t warnings in 32 bit build
#ifdef _M_IX86
@ -145,10 +145,42 @@ public:
std::array<byte, N>& asArray() { return m_data; }
std::array<byte, N> const& asArray() const { return m_data; }
// generic std::hash compatible function object
struct hash
{
size_t operator()(FixedHash const& value) const
{
size_t h = 0;
for (auto i: value.m_data)
h = (h << 5 - h) + i;
return h;
}
};
private:
std::array<byte, N> m_data;
};
// fast equality for h256
template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
{
const uint64_t* hash1 = (const uint64_t*)this->data();
const uint64_t* hash2 = (const uint64_t*)_other.data();
return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]);
}
// fast std::hash compatible hash function object for h256
template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
{
const uint64_t*data = (const uint64_t*)value.data();
uint64_t hash = data[0];
hash ^= data[1];
hash ^= data[2];
hash ^= data[3];
return (size_t)hash;
}
template <unsigned N>
inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
{
@ -181,7 +213,6 @@ using HexMap = std::map<bytes, std::string>;
static const u256 Invalid256 = ~(u256)0;
static const bytes NullBytes;
/// Logging
class NullOutputStream
{
@ -224,8 +255,8 @@ public:
{
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
char buf[24];
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails
sstr << Id::name() << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : "");
}
}
@ -648,3 +679,9 @@ bytes contents(std::string const& _file);
void writeFile(std::string const& _file, bytes const& _data);
}
namespace std
{
// forward std::hash<eth::h256> to eth::h256::hash
template<> struct hash<eth::h256>: eth::h256::hash {};
}

177
libethereum/Instruction.cpp

@ -138,17 +138,25 @@ static void appendCode(u256s& o_code, vector<unsigned>& o_locs, u256s _code, vec
static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256s& o_code, vector<unsigned>& o_locs)
{
std::map<std::string, Instruction> const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD } };
std::map<std::string, Instruction> const c_binary = { { "<", Instruction::LT }, { "<=", Instruction::LE }, { ">", Instruction::GT }, { ">=", Instruction::GE }, { "=", Instruction::EQ }, { "!=", Instruction::NOT } };
std::map<std::string, Instruction> const c_unary = { { "!", Instruction::NOT } };
std::set<char> const c_allowed = { '+', '-', '*', '/', '%', '<', '>', '=', '!' };
bool exec = false;
while (d != e)
{
// skip to next token
for (; d != e && !isalnum(*d) && *d != '(' && *d != ')' && *d != '_' && *d != '"'; ++d) {}
for (; d != e && !isalnum(*d) && *d != '(' && *d != ')' && *d != '_' && *d != '"' && !c_allowed.count(*d) && *d != ';'; ++d) {}
if (d == e)
break;
switch (*d)
{
case ';':
for (; d != e && *d != '\n'; ++d) {}
break;
case '(':
exec = true;
++d;
@ -186,7 +194,7 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
else
{
char const* s = d;
for (; d != e && (isalnum(*d) || *d == '_'); ++d) {}
for (; d != e && (isalnum(*d) || *d == '_' || c_allowed.count(*d)); ++d) {}
t = string(s, d - s);
if (isdigit(t[0]))
{
@ -340,6 +348,107 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
break;
}
}
else if (t == "AND")
{
vector<u256s> codes;
vector<vector<unsigned>> locs;
while (d != e)
{
codes.resize(codes.size() + 1);
locs.resize(locs.size() + 1);
if (!compileLispFragment(d, e, _quiet, codes.back(), locs.back()))
break;
}
// last one is empty.
if (codes.size() < 2)
return false;
codes.pop_back();
locs.pop_back();
vector<unsigned> ends;
if (codes.size() > 1)
{
o_code.push_back(Instruction::PUSH);
o_code.push_back(0);
for (unsigned i = 1; i < codes.size(); ++i)
{
// Push the false location.
o_code.push_back(Instruction::PUSH);
ends.push_back((unsigned)o_code.size());
o_locs.push_back(ends.back());
o_code.push_back(0);
// Check if true - predicate
appendCode(o_code, o_locs, codes[i - 1], locs[i - 1]);
// Jump to end...
o_code.push_back(Instruction::NOT);
o_code.push_back(Instruction::JMPI);
}
o_code.push_back(Instruction::POP);
}
// Check if true - predicate
appendCode(o_code, o_locs, codes.back(), locs.back());
// At end now.
for (auto i: ends)
o_code[i] = o_code.size();
}
else if (t == "OR")
{
vector<u256s> codes;
vector<vector<unsigned>> locs;
while (d != e)
{
codes.resize(codes.size() + 1);
locs.resize(locs.size() + 1);
if (!compileLispFragment(d, e, _quiet, codes.back(), locs.back()))
break;
}
// last one is empty.
if (codes.size() < 2)
return false;
codes.pop_back();
locs.pop_back();
vector<unsigned> ends;
if (codes.size() > 1)
{
o_code.push_back(Instruction::PUSH);
o_code.push_back(1);
for (unsigned i = 1; i < codes.size(); ++i)
{
// Push the false location.
o_code.push_back(Instruction::PUSH);
ends.push_back((unsigned)o_code.size());
o_locs.push_back(ends.back());
o_code.push_back(0);
// Check if true - predicate
appendCode(o_code, o_locs, codes[i - 1], locs[i - 1]);
// Jump to end...
o_code.push_back(Instruction::JMPI);
}
o_code.push_back(Instruction::POP);
}
// Check if true - predicate
appendCode(o_code, o_locs, codes.back(), locs.back());
// At end now.
for (auto i: ends)
o_code[i] = o_code.size();
}
else
{
auto it = c_instructions.find(t);
@ -360,8 +469,68 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
o_code.push_back(it->second);
}
}
else if (!_quiet)
cwarn << "Unknown assembler token" << t;
else
{
auto it = c_arith.find(t);
if (it != c_arith.end())
{
int i = 0;
while (d != e)
{
u256s codes;
vector<unsigned> locs;
if (compileLispFragment(d, e, _quiet, codes, locs))
{
appendCode(o_code, o_locs, codes, locs);
if (i)
o_code.push_back((u256)it->second);
++i;
}
else
break;
}
}
else
{
auto it = c_binary.find(t);
if (it != c_binary.end())
{
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second))
codes.push_back(pair<u256s, vector<unsigned>>());
codes.pop_back();
int i = codes.size();
if (i > 2)
cwarn << "Greater than two arguments given to binary operator" << t << "; using first two only.";
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
if (--i < 2)
appendCode(o_code, o_locs, it->first, it->second);
if (it->second == Instruction::NOT)
o_code.push_back(Instruction::EQ);
o_code.push_back((u256)it->second);
}
else
{
auto it = c_unary.find(t);
if (it != c_unary.end())
{
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second))
codes.push_back(pair<u256s, vector<unsigned>>());
codes.pop_back();
int i = codes.size();
if (i > 1)
cwarn << "Greater than one argument given to unary operator" << t << "; using first only.";
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
if (--i < 1)
appendCode(o_code, o_locs, it->first, it->second);
o_code.push_back(it->second);
}
else if (!_quiet)
cwarn << "Unknown assembler token" << t;
}
}
}
}
}

26
libethereum/PeerNetwork.cpp

@ -483,19 +483,21 @@ bool PeerSession::checkPacket(bytesConstRef _msg)
void PeerSession::sendDestroy(bytes& _msg)
{
clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg);
if (!checkPacket(bytesConstRef(&*buffer)))
if (!checkPacket(bytesConstRef(&_msg)))
{
cwarn << "INVALID PACKET CONSTRUCTED!";
}
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
auto self(shared_from_this());
bytes* buffer = new bytes(std::move(_msg));
ba::async_write(m_socket, ba::buffer(*buffer), [self,buffer](boost::system::error_code ec, std::size_t length)
{
delete buffer;
if (ec)
{
cwarn << "Error sending: " << ec.message();
dropped();
self->dropped();
}
// cbug << length << " bytes written (EC: " << ec << ")";
});
@ -504,17 +506,21 @@ void PeerSession::sendDestroy(bytes& _msg)
void PeerSession::send(bytesConstRef _msg)
{
clogS(NetLeft) << RLP(_msg.cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>(_msg.toBytes());
if (!checkPacket(_msg))
{
cwarn << "INVALID PACKET CONSTRUCTED!";
}
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
auto self(shared_from_this());
bytes* buffer = new bytes(_msg.toBytes());
ba::async_write(m_socket, ba::buffer(*buffer), [self,buffer](boost::system::error_code ec, std::size_t length)
{
delete buffer;
if (ec)
{
cwarn << "Error sending: " << ec.message();
dropped();
self->dropped();
}
// cbug << length << " bytes written (EC: " << ec << ")";
});
@ -568,7 +574,7 @@ void PeerSession::start()
void PeerSession::doRead()
{
auto self(shared_from_this());
m_socket.async_read_some(boost::asio::buffer(m_data), [this, self](boost::system::error_code ec, std::size_t length)
m_socket.async_read_some(boost::asio::buffer(m_data), [this,self](boost::system::error_code ec, std::size_t length)
{
if (ec)
{

8
libethereum/TrieDB.h

@ -31,14 +31,6 @@ namespace ldb = leveldb;
namespace eth
{
class DBFace
{
public:
virtual std::string node(h256 _h) const = 0;
virtual void insertNode(h256 _h, bytesConstRef _v) = 0;
virtual void killNode(h256 _h) = 0;
};
class BasicMap
{
public:

19
libethereum/VM.h

@ -264,6 +264,7 @@ template <class Ext> void eth::VM::go(Ext& _ext, uint64_t _steps)
break;
case Instruction::SHA256:
{
require(1);
uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32);
m_stack.pop_back();
@ -282,6 +283,7 @@ template <class Ext> void eth::VM::go(Ext& _ext, uint64_t _steps)
}
case Instruction::RIPEMD160:
{
require(1);
uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32);
m_stack.pop_back();
@ -419,6 +421,7 @@ template <class Ext> void eth::VM::go(Ext& _ext, uint64_t _steps)
}
case Instruction::SHA3:
{
require(1);
uint s = (uint)std::min(m_stack.back(), (u256)(m_stack.size() - 1) * 32);
m_stack.pop_back();
@ -482,11 +485,11 @@ template <class Ext> void eth::VM::go(Ext& _ext, uint64_t _steps)
{
require(1);
#ifdef __clang__
auto mFinder = tempMem.find(stack.back());
if (mFinder != tempMem.end())
stack.back() = mFinder->second;
auto mFinder = m_temp.find(m_stack.back());
if (mFinder != m_temp.end())
m_stack.back() = mFinder->second;
else
stack.back() = 0;
m_stack.back() = 0;
#else
m_stack.back() = m_temp[m_stack.back()];
#endif
@ -496,11 +499,11 @@ template <class Ext> void eth::VM::go(Ext& _ext, uint64_t _steps)
{
require(2);
#ifdef __clang__
auto mFinder = tempMem.find(stack.back());
if (mFinder == tempMem.end())
tempMem.insert(make_pair(stack.back(), stack[stack.size() - 2]));
auto mFinder = m_temp.find(m_stack.back());
if (mFinder == m_temp.end())
m_temp.insert(std::make_pair(m_stack.back(), m_stack[m_stack.size() - 2]));
else
mFinder->second = stack[stack.size() - 2];
mFinder->second = m_stack[m_stack.size() - 2];
#else
m_temp[m_stack.back()] = m_stack[m_stack.size() - 2];
#endif

14
release.sh

@ -1,7 +1,12 @@
#!/bin/bash
dist="saucy"
version=$1
version=$(grep "define ETH_VERSION" libethereum/Common.h | cut -d ' ' -f 3)
branch="$(git branch | grep \* | cut -c 3-)"
if [[ ! "$1" == "" ]]; then
version=$1
fi
if [[ ! "$3" == "" ]]; then
if [[ ! "$4" == "" ]]; then
@ -25,12 +30,9 @@ cd /tmp
echo Checking out...
git clone $opwd
cd cpp-ethereum
git checkout "$branch"
if [ "$1" == "" ]; then
archdir="cpp-ethereum-$(date +%Y%m%d)"
else
archdir="cpp-ethereum-$version"
fi
archdir="cpp-ethereum-$version"
archfile="$archdir.tar.bz2"
echo Cleaning backup files...

1
test/crypto.cpp

@ -30,6 +30,7 @@ using namespace eth;
int cryptoTest()
{
cnote << "Testing Crypto...";
secp256k1_start();
KeyPair p(Secret(fromUserHex("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4")));

1
test/dagger.cpp

@ -28,6 +28,7 @@ using namespace eth;
int daggerTest()
{
cnote << "Testing Dagger...";
// Test dagger
{
auto s = steady_clock::now();

69
test/hexPrefix.cpp

@ -20,38 +20,51 @@
* Main test functions.
*/
#include <fstream>
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include "TrieCommon.h"
using namespace std;
using namespace eth;
namespace js = json_spirit;
int hexPrefixTest()
namespace eth
{
template <> class UnitTest<3>
{
/*
* Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1
* [0,0,1,2,3,4,5] 0x10012345
* [0,1,2,3,4,5] 0x00012345
* [1,2,3,4,5] 0x112345
* [0,0,1,2,3,4] 0x00001234
* [0,1,2,3,4] 0x101234
* [1,2,3,4] 0x001234
* [0,0,1,2,3,4,5,T] 0x30012345
* [0,0,1,2,3,4,T] 0x20001234
* [0,1,2,3,4,5,T] 0x20012345
* [1,2,3,4,5,T] 0x312345
* [1,2,3,4,T] 0x201234
*/
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4, 5}, false)) == "10012345");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4, 5}, false)) == "00012345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4, 5}, false)) == "112345");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4}, false)) == "00001234");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4}, false)) == "101234");
assert(asHex(hexPrefixEncode({1, 2, 3, 4}, false)) == "001234");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4, 5}, true)) == "30012345");
assert(asHex(hexPrefixEncode({0, 0, 1, 2, 3, 4}, true)) == "20001234");
assert(asHex(hexPrefixEncode({0, 1, 2, 3, 4, 5}, true)) == "20012345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4, 5}, true)) == "312345");
assert(asHex(hexPrefixEncode({1, 2, 3, 4}, true)) == "201234");
return 0;
public:
int operator()()
{
js::mValue v;
string s = asString(contents("../../tests/hexencodetest.json"));
js::read_string(s, v);
bool passed = true;
for (auto& i: v.get_obj())
{
js::mObject& o = i.second.get_obj();
cnote << i.first;
bytes v;
for (auto& i: o["seq"].get_array())
v.push_back(i.get_int());
auto e = hexPrefixEncode(v, o["term"].get_bool());
if (!o["out"].is_null() && o["out"].get_str() != asHex(e))
{
cwarn << "Test failed.";
cwarn << "Test says:" << o["out"].get_str();
cwarn << "Impl says:" << asHex(e);
passed = false;
}
}
return passed ? 0 : 1;
}
};
}
int hexPrefixTest()
{
cnote << "Testing Hex-Prefix-Encode...";
return UnitTest<3>()();
}

18
test/main.cpp

@ -42,14 +42,16 @@ int main(int, char**)
std::cout << asHex(s.out()) << std::endl;
std::cout << sha3(s.out()) << std::endl;*/
hexPrefixTest();
rlpTest();
trieTest();
daggerTest();
cryptoTest();
vmTest();
// stateTest();
// peerTest(argc, argv);
int r = 0;
r += hexPrefixTest();
r += rlpTest();
r += trieTest();
r += vmTest();
r += cryptoTest(); // TODO: Put in tests repo.
// r += daggerTest();
// r += stateTest();
// r += peerTest(argc, argv);
assert(!r);
return 0;
}

90
test/rlp.cpp

@ -20,48 +20,70 @@
* RLP test functions.
*/
#include <fstream>
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include <RLP.h>
using namespace std;
using namespace eth;
namespace js = json_spirit;
int rlpTest()
namespace eth
{
// int of value 15
assert(RLP("\x0f") == 15);
assert(asString(rlp(15)) == "\x0f");
// 3-character string
assert(RLP("\x83""dog") == "dog");
assert(asString(rlp("dog")) == "\x83""dog");
// 2-item list
string twoItemListString = "\xc5\x0f\x83""dog";
RLP twoItemList(twoItemListString);
assert(twoItemList.itemCount() == 2);
assert(twoItemList[0] == 15);
assert(twoItemList[1] == "dog");
assert(asString(rlpList(15, "dog")) == "\xc5\x0f\x83""dog");
// null
assert(RLP("\x80") == "");
assert(asString(rlp("")) == "\x80");
// 1-byte (8-bit) int
assert(RLP("\x81\x80") == 128);
assert(asString(rlp(128)) == "\x81\x80");
// 2-byte (16-bit) int
assert(RLP("\x82\x01\x01") == 257);
assert(asString(rlp(257)) == "\x82\x01\x01");
template <> class UnitTest<2>
{
public:
static void buildRLP(js::mValue& _v, RLPStream& _rlp)
{
if (_v.type() == js::array_type)
{
RLPStream s;
for (auto& i: _v.get_array())
buildRLP(i, s);
_rlp.appendList(s.out());
}
else if (_v.type() == js::int_type)
_rlp.append(_v.get_uint64());
else if (_v.type() == js::str_type)
{
auto s = _v.get_str();
if (s.size() && s[0] == '#')
_rlp.append(bigint(s.substr(1)));
else
_rlp.append(s);
}
}
// 32-byte (256-bit) int
assert(RLP("\xa0\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
assert(asString(rlp(bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"))) == "\xa0\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f");
int operator()()
{
js::mValue v;
string s = asString(contents("../../tests/rlptest.json"));
js::read_string(s, v);
bool passed = true;
for (auto& i: v.get_obj())
{
js::mObject& o = i.second.get_obj();
cnote << i.first;
RLPStream s;
buildRLP(o["in"], s);
if (!o["out"].is_null() && o["out"].get_str() != asHex(s.out()))
{
cwarn << "Test failed.";
cwarn << "Test says:" << o["out"].get_str();
cwarn << "Impl says:" << asHex(s.out());
passed = false;
}
}
return passed ? 0 : 1;
}
// 56-character string.
assert(RLP("\xb8\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit") == "Lorem ipsum dolor sit amet, consectetur adipisicing elit");
assert(asString(rlp("Lorem ipsum dolor sit amet, consectetur adipisicing elit")) == "\xb8\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit");
};
return 0;
}
int rlpTest()
{
cnote << "Testing RLP...";
return UnitTest<2>()();
}

2
test/state.cpp

@ -30,6 +30,8 @@ using namespace eth;
int stateTest()
{
cnote << "Testing State...";
KeyPair me = sha3("Gav Wood");
KeyPair myMiner = sha3("Gav's Miner");
// KeyPair you = sha3("123");

54
test/trie.cpp

@ -20,6 +20,9 @@
* Trie test functions.
*/
#include <fstream>
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include <random>
#include <TrieHash.h>
#include <TrieDB.h>
@ -27,6 +30,53 @@
using namespace std;
using namespace eth;
namespace js = json_spirit;
namespace eth
{
unsigned fac(unsigned _i) { return _i > 2 ? _i * fac(_i - 1) : _i; }
template <> class UnitTest<4>
{
public:
int operator()()
{
js::mValue v;
string s = asString(contents("../../tests/trietest.json"));
js::read_string(s, v);
bool passed = true;
for (auto& i: v.get_obj())
{
js::mObject& o = i.second.get_obj();
cnote << i.first;
vector<pair<string, string>> ss;
for (auto& i: o["in"].get_obj())
ss.push_back(make_pair(i.first, i.second.get_str()));
for (unsigned j = 0; j < fac(ss.size()); ++j)
{
next_permutation(ss.begin(), ss.end());
BasicMap m;
GenericTrieDB<BasicMap> t(&m);
t.init();
for (auto const& k: ss)
t.insert(k.first, k.second);
if (!o["root"].is_null() && o["root"].get_str() != asHex(t.root().asArray()))
{
cwarn << "Test failed on permutation " << j;
cwarn << "Test says:" << o["root"].get_str();
cwarn << "Impl says:" << asHex(t.root().asArray());
passed = false;
}
}
}
return passed ? 0 : 1;
}
};
}
inline h256 stringMapHash256(StringMap const& _s)
{
return hash256(_s);
@ -34,6 +84,10 @@ inline h256 stringMapHash256(StringMap const& _s)
int trieTest()
{
cnote << "Testing Trie...";
return UnitTest<4>()();
// More tests...
{
BasicMap m;
GenericTrieDB<BasicMap> t(&m);

81
test/vm.cpp

@ -43,8 +43,34 @@ public:
ExtVMFace(Address(), Address(), 0, u256s(), _fees, _previousBlock, _currentBlock, _currentNumber)
{}
u256 store(u256 _n) { return get<3>(addresses[myAddress])[_n]; }
void setStore(u256 _n, u256 _v) { get<3>(addresses[myAddress])[_n] = _v; }
u256 store(u256 _n)
{
#ifdef __clang__
tuple<u256, u256, u256, map<u256, u256> > & address = addresses[myAddress];
map<u256, u256> & third = get<3>(address);
auto sFinder = third.find(_n);
if (sFinder != third.end())
return sFinder->second;
else
return 0;
#else
return get<3>(addresses[myAddress])[_n];
#endif
}
void setStore(u256 _n, u256 _v)
{
#ifdef __clang__
tuple<u256, u256, u256, map<u256, u256> > & address = addresses[myAddress];
map<u256, u256> & third = get<3>(address);
auto sFinder = third.find(_n);
if (sFinder != third.end())
sFinder->second = _v;
else
third.insert(std::make_pair(_n, _v));
#else
get<3>(addresses[myAddress])[_n] = _v;
#endif
}
void mktx(Transaction& _t)
{
if (get<0>(addresses[myAddress]) >= _t.value)
@ -58,7 +84,20 @@ public:
u256 balance(Address _a) { return get<0>(addresses[_a]); }
void payFee(bigint _fee) { get<0>(addresses[myAddress]) = (u256)(get<0>(addresses[myAddress]) - _fee); }
u256 txCount(Address _a) { return get<1>(addresses[_a]); }
u256 extro(Address _a, u256 _pos) { return get<3>(addresses[_a])[_pos]; }
u256 extro(Address _a, u256 _pos)
{
#ifdef __clang__
tuple<u256, u256, u256, map<u256, u256> > & address = addresses[_a];
map<u256, u256> & third = get<3>(address);
auto sFinder = third.find(_pos);
if (sFinder != third.end())
return sFinder->second;
else
return 0;
#else
return get<3>(addresses[_a])[_pos];
#endif
}
u256 extroPrice(Address _a) { return get<2>(addresses[_a]); }
void suicide(Address _a)
{
@ -86,7 +125,19 @@ public:
get<1>(addresses[_a]) = _myNonce;
get<2>(addresses[_a]) = 0;
for (unsigned i = 0; i < _myData.size(); ++i)
#ifdef __clang__
{
tuple<u256, u256, u256, map<u256, u256> > & address = addresses[_a];
map<u256, u256> & third = get<3>(address);
auto sFinder = third.find(i);
if (sFinder != third.end())
sFinder->second = _myData[i];
else
third.insert(std::make_pair(i, _myData[i]));
}
#else
get<3>(addresses[_a])[i] = _myData[i];
#endif
}
mObject exportEnv()
@ -194,13 +245,36 @@ public:
{
u256 adr(j.first);
for (auto const& k: j.second.get_array())
#ifdef __clang__
{
map<u256, u256> & third = get<3>(a);
auto sFinder = third.find(adr);
if (sFinder != third.end())
sFinder->second = toInt(k);
else
third.insert(std::make_pair(adr, toInt(k)));
adr++;
}
#else
get<3>(a)[adr++] = toInt(k);
#endif
}
if (o.count("code"))
{
u256s d = compileLisp(o["code"].get_str());
for (unsigned i = 0; i < d.size(); ++i)
#ifdef __clang__
{
map<u256, u256> & third = get<3>(a);
auto sFinder = third.find(i);
if (sFinder != third.end())
sFinder->second = d[i];
else
third.insert(std::make_pair(i, d[i]));
}
#else
get<3>(a)[(u256)i] = d[i];
#endif
}
}
}
@ -372,6 +446,7 @@ public:
int vmTest()
{
cnote << "Testing VM...";
return UnitTest<1>()();
}

82
test/vmtests.json

@ -1,29 +1,83 @@
{
"suicide": {
"env" : {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"previousNonce" : "9c9c6567b5ec0c5f3f25df79be42707090f1e62e9db84cbb556ae2a2f6ccccae",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"feeMultiplier" : 1
},
"pre" : {
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : 1000000000000000000,
"nonce" : 0,
"code" : "(suicide (txsender))"
"balance" : 1000000000000000000,
"nonce" : 0,
"code" : "(suicide (txsender))"
}
},
"exec" : [
},
"exec" : [
{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"sender" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : 1000000000000000000,
"data" : [
]
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"sender" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : 1000000000000000000,
"data" : [
]
}
]
]
},
"arith": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"previousNonce" : "9c9c6567b5ec0c5f3f25df79be42707090f1e62e9db84cbb556ae2a2f6ccccae",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"feeMultiplier" : 1
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : 1000000000000000000,
"nonce" : 0,
"code" : "(seq (mktx (txsender) (+ 2 2 (* 4 4 4) (/ 2 2) (% 3 2) (- 8 2 2)) 0) )"
}
},
"exec" : [
{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"sender" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : 1000000000000000000,
"data" : [
]
}
]
},
"boolean": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"previousNonce" : "9c9c6567b5ec0c5f3f25df79be42707090f1e62e9db84cbb556ae2a2f6ccccae",
"currentDifficulty" : "256",
"currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"feeMultiplier" : 1
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : 1000000000000000000,
"nonce" : 0,
"code" : "(seq (when (and 1 1) (mktx (txsender) 2 0)) (when (and 1 0) (mktx (txsender) 3 0)) (when (and 0 1) (mktx (txsender) 4 0)) (when (and 0 0) (mktx (txsender) 5 0)) (when (or 1 1) (mktx (txsender) 12 0)) (when (or 1 0) (mktx (txsender) 13 0)) (when (or 0 1) (mktx (txsender) 14 0)) (when (or 0 0) (mktx (txsender) 15 0)) )"
}
},
"exec" : [
{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"sender" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : 1000000000000000000,
"data" : [
]
}
]
},
"mktx": {

15
windows/bootstrap.sh

@ -7,12 +7,25 @@
# - Visual Studio Express 2013 for Desktop
# - On PATH: bash, git, git-svn, curl, sed, 7z
error_exit() {
echo $1 1>&2
exit 1
}
for i in python perl curl git sed 7z; do
which $i &>/dev/null || error_exit "Could not find $i on PATH"
done
if [ ! -d "$VS120COMNTOOLS" ]; then
error_exit "Couldn't find Visual Studio 2013"
fi
if [[ ! $@ ]] || [ $1 == "fetch" ]; then
# fetch ethereum (develop branch)
if [ ! -d cpp-ethereum ]; then
(set -x; git clone https://github.com/ethereum/cpp-ethereum.git)
cd cpp-ethereum
(set -x; git checkout origin/develop)
(set -x; git checkout -b develop origin/develop)
cd ..
echo
fi

Loading…
Cancel
Save