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 . 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 See TODO
## License ### License
See 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. 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); 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"); 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); m_webCtrl.get(r);
srand(time(0)); srand(time(0));
@ -181,7 +181,7 @@ Address Main::fromString(QString const& _a) const
void Main::on_about_triggered() 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() void Main::writeSettings()

5
json_spirit/json_spirit_writer_template.h

@ -25,7 +25,9 @@ namespace json_spirit
return 'A' - 10 + ch; 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 ) String_type non_printable_to_string( unsigned int c )
{ {
typedef typename String_type::value_type Char_type; typedef typename String_type::value_type Char_type;
@ -41,6 +43,7 @@ namespace json_spirit
return result; return result;
} }
#pragma GCC diagnostic pop
template< typename Char_type, class String_type > template< typename Char_type, class String_type >
bool add_esc_char( Char_type c, String_type& s ) 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 BlockDetails const& BlockChain::details(h256 _h) const
{ {
std::map<h256, BlockDetails>::const_iterator it; BlockDetailsHash::const_iterator it;
bool fetchRequired; bool fetchRequired;
{ {
lock_guard<mutex> l(m_lock); lock_guard<mutex> l(m_lock);
@ -290,7 +290,7 @@ BlockDetails const& BlockChain::details(h256 _h) const
{ {
lock_guard<mutex> l(m_lock); lock_guard<mutex> l(m_lock);
bool ok; 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; return it->second;

6
libethereum/BlockChain.h

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

45
libethereum/Common.h

@ -24,7 +24,7 @@
#pragma once #pragma once
// define version // 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 // way to many uint to size_t warnings in 32 bit build
#ifdef _M_IX86 #ifdef _M_IX86
@ -145,10 +145,42 @@ public:
std::array<byte, N>& asArray() { return m_data; } std::array<byte, N>& asArray() { return m_data; }
std::array<byte, N> const& asArray() const { 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: private:
std::array<byte, N> m_data; 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> template <unsigned N>
inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h) 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 u256 Invalid256 = ~(u256)0;
static const bytes NullBytes; static const bytes NullBytes;
/// Logging /// Logging
class NullOutputStream class NullOutputStream
{ {
@ -224,8 +255,8 @@ public:
{ {
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
char buf[24]; char buf[24];
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0) if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails buf[0] = '\0'; // empty if case strftime fails
sstr << Id::name() << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : ""); 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); 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) 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; bool exec = false;
while (d != e) while (d != e)
{ {
// skip to next token // 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) if (d == e)
break; break;
switch (*d) switch (*d)
{ {
case ';':
for (; d != e && *d != '\n'; ++d) {}
break;
case '(': case '(':
exec = true; exec = true;
++d; ++d;
@ -186,7 +194,7 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
else else
{ {
char const* s = d; 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); t = string(s, d - s);
if (isdigit(t[0])) if (isdigit(t[0]))
{ {
@ -340,6 +348,107 @@ static bool compileLispFragment(char const*& d, char const* e, bool _quiet, u256
break; 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 else
{ {
auto it = c_instructions.find(t); 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); o_code.push_back(it->second);
} }
} }
else if (!_quiet) else
cwarn << "Unknown assembler token" << t; {
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) void PeerSession::sendDestroy(bytes& _msg)
{ {
clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8)); clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg); if (!checkPacket(bytesConstRef(&_msg)))
if (!checkPacket(bytesConstRef(&*buffer)))
{ {
cwarn << "INVALID PACKET CONSTRUCTED!"; 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) if (ec)
{ {
cwarn << "Error sending: " << ec.message(); cwarn << "Error sending: " << ec.message();
dropped(); self->dropped();
} }
// cbug << length << " bytes written (EC: " << ec << ")"; // cbug << length << " bytes written (EC: " << ec << ")";
}); });
@ -504,17 +506,21 @@ void PeerSession::sendDestroy(bytes& _msg)
void PeerSession::send(bytesConstRef _msg) void PeerSession::send(bytesConstRef _msg)
{ {
clogS(NetLeft) << RLP(_msg.cropped(8)); clogS(NetLeft) << RLP(_msg.cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>(_msg.toBytes());
if (!checkPacket(_msg)) if (!checkPacket(_msg))
{ {
cwarn << "INVALID PACKET CONSTRUCTED!"; 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) if (ec)
{ {
cwarn << "Error sending: " << ec.message(); cwarn << "Error sending: " << ec.message();
dropped(); self->dropped();
} }
// cbug << length << " bytes written (EC: " << ec << ")"; // cbug << length << " bytes written (EC: " << ec << ")";
}); });
@ -568,7 +574,7 @@ void PeerSession::start()
void PeerSession::doRead() void PeerSession::doRead()
{ {
auto self(shared_from_this()); 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) if (ec)
{ {

8
libethereum/TrieDB.h

@ -31,14 +31,6 @@ namespace ldb = leveldb;
namespace eth 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 class BasicMap
{ {
public: public:

19
libethereum/VM.h

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

14
release.sh

@ -1,7 +1,12 @@
#!/bin/bash #!/bin/bash
dist="saucy" 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 [[ ! "$3" == "" ]]; then
if [[ ! "$4" == "" ]]; then if [[ ! "$4" == "" ]]; then
@ -25,12 +30,9 @@ cd /tmp
echo Checking out... echo Checking out...
git clone $opwd git clone $opwd
cd cpp-ethereum cd cpp-ethereum
git checkout "$branch"
if [ "$1" == "" ]; then archdir="cpp-ethereum-$version"
archdir="cpp-ethereum-$(date +%Y%m%d)"
else
archdir="cpp-ethereum-$version"
fi
archfile="$archdir.tar.bz2" archfile="$archdir.tar.bz2"
echo Cleaning backup files... echo Cleaning backup files...

1
test/crypto.cpp

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

1
test/dagger.cpp

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

69
test/hexPrefix.cpp

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

90
test/rlp.cpp

@ -20,48 +20,70 @@
* RLP test functions. * RLP test functions.
*/ */
#include <fstream>
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include <RLP.h> #include <RLP.h>
using namespace std; using namespace std;
using namespace eth; 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 template <> class UnitTest<2>
assert(RLP("\x82\x01\x01") == 257); {
assert(asString(rlp(257)) == "\x82\x01\x01"); 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 int operator()()
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"); 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() int stateTest()
{ {
cnote << "Testing State...";
KeyPair me = sha3("Gav Wood"); KeyPair me = sha3("Gav Wood");
KeyPair myMiner = sha3("Gav's Miner"); KeyPair myMiner = sha3("Gav's Miner");
// KeyPair you = sha3("123"); // KeyPair you = sha3("123");

54
test/trie.cpp

@ -20,6 +20,9 @@
* Trie test functions. * Trie test functions.
*/ */
#include <fstream>
#include "../json_spirit/json_spirit_reader_template.h"
#include "../json_spirit/json_spirit_writer_template.h"
#include <random> #include <random>
#include <TrieHash.h> #include <TrieHash.h>
#include <TrieDB.h> #include <TrieDB.h>
@ -27,6 +30,53 @@
using namespace std; using namespace std;
using namespace eth; 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) inline h256 stringMapHash256(StringMap const& _s)
{ {
return hash256(_s); return hash256(_s);
@ -34,6 +84,10 @@ inline h256 stringMapHash256(StringMap const& _s)
int trieTest() int trieTest()
{ {
cnote << "Testing Trie...";
return UnitTest<4>()();
// More tests...
{ {
BasicMap m; BasicMap m;
GenericTrieDB<BasicMap> t(&m); GenericTrieDB<BasicMap> t(&m);

81
test/vm.cpp

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

82
test/vmtests.json

@ -1,29 +1,83 @@
{ {
"suicide": { "suicide": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"previousNonce" : "9c9c6567b5ec0c5f3f25df79be42707090f1e62e9db84cbb556ae2a2f6ccccae", "previousNonce" : "9c9c6567b5ec0c5f3f25df79be42707090f1e62e9db84cbb556ae2a2f6ccccae",
"currentDifficulty" : "256", "currentDifficulty" : "256",
"currentTimestamp" : 1, "currentTimestamp" : 1,
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"feeMultiplier" : 1 "feeMultiplier" : 1
}, },
"pre" : { "pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : 1000000000000000000, "balance" : 1000000000000000000,
"nonce" : 0, "nonce" : 0,
"code" : "(suicide (txsender))" "code" : "(suicide (txsender))"
} }
}, },
"exec" : [ "exec" : [
{ {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"sender" : "cd1722f3947def4cf144679da39c4c32bdc35681", "sender" : "cd1722f3947def4cf144679da39c4c32bdc35681",
"value" : 1000000000000000000, "value" : 1000000000000000000,
"data" : [ "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": { "mktx": {

15
windows/bootstrap.sh

@ -7,12 +7,25 @@
# - Visual Studio Express 2013 for Desktop # - Visual Studio Express 2013 for Desktop
# - On PATH: bash, git, git-svn, curl, sed, 7z # - 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 if [[ ! $@ ]] || [ $1 == "fetch" ]; then
# fetch ethereum (develop branch) # fetch ethereum (develop branch)
if [ ! -d cpp-ethereum ]; then if [ ! -d cpp-ethereum ]; then
(set -x; git clone https://github.com/ethereum/cpp-ethereum.git) (set -x; git clone https://github.com/ethereum/cpp-ethereum.git)
cd cpp-ethereum cd cpp-ethereum
(set -x; git checkout origin/develop) (set -x; git checkout -b develop origin/develop)
cd .. cd ..
echo echo
fi fi

Loading…
Cancel
Save